算法-04 动态规划法 回溯法

1 回溯法之 八皇后

要求:在八横八纵的网格中,找到任意八个点,且这八个点不能在同一行 也不再同一列。并且也不在任意一条对角线上。
思路:遍历每一列,判断这一列前面的列已经放好了的位置。则此行不能再放。
再判断这一列所有和这个位置构成对角线的点。这个点也不能在放。

	// 每一行 每一列的个数
	private int MAXQUEEN = 8;
	// 记录每一列皇后的下标
	private int col[] = new int[MAXQUEEN];
	// 记录方案数
	private int num = 0;
public static void main(String[] args) {
		Queen queen = new Queen();
		queen.getCount(0);
	}
	// 获取第n列皇后的 下标
	private void getCount(int n) {
		boolean[] row = new boolean[MAXQUEEN];

		for (int m = 0; m < n; m++) {
			// 其他列在此行中 已有皇后
			row[col[m]] = true;

			int d = n - m;

			// 判断正斜方向上是否可以放皇后
			if (col[m] - d >= 0) {
				row[col[m] - d] = true;
			}

			// 判断反斜方向是否可以放皇后
			if (col[m] + d <= MAXQUEEN - 1) {
				row[col[m] + d] = true;
			}

		}

		// 已经知道哪些点不可以放
		for (int i = 0; i < MAXQUEEN; i++) {
			if (row[i]) {
				continue;
			}
			col[n] = i;
			if (n < MAXQUEEN - 1) {
				getCount(n + 1);
			} else {
				num++;
				printQueen();
			}

		}

	}

	// 打印皇后的位置
	private void printQueen() {
		// 遍历行
		System.out.println("第" + num + "种方案");
		for (int i = 0; i < MAXQUEEN; i++) {
			// 遍历列
			for (int j = 0; j < MAXQUEEN; j++) {
				if (col[j] == i) {
					System.out.print("0 ");
				} else {
					System.out.print("+ ");
				}
			}
			System.out.println();
		}
	}

这里写图片描述

2 大数相乘

如果用int值直接相乘。那么有些不在int范围内的值无法计算。
大数相乘用输出字符串的形式来计算出两个较大值的乘积。

public static void main(String[] args) {
		BigCountMultyply bigCountMultyply = new BigCountMultyply();
		bigCountMultyply.setCharArray("4", "5");
	}
	
	//把字符串转成倒过来的char[]
	private void setCharArray(String strNum1,String strNum2){
		char[] charArray1 = exchangeCharArray(strNum1.toCharArray());
		char[] charArray2 = exchangeCharArray(strNum2.toCharArray());
		
		multyply(charArray1,charArray2);
	}
	
	//把char[] 倒过来
	private char[] exchangeCharArray(char[] charArray){
		int len = charArray.length;
		for(int i=0;i<len/2;i++){
			charArray[i]+=charArray[len-i-1];
			charArray[len-i-1] = (char) (charArray[i]-charArray[len-i-1]);
			charArray[i] = (char) (charArray[i] - charArray[len-i-1]);
		}
		return charArray;
	}
private void multyply(char[] a,char[] b){
		int len = a.length+b.length;
		int[] value = new int[len];
		
		//相乘
		for(int i=0;i<a.length;i++){
			for(int j=0;j<b.length;j++){
				value[i+j]+=Integer.parseInt(String.valueOf(a[i]))*Integer.parseInt(String.valueOf(b[j]));
			}
		}
		
		//进位
		for(int i=0;i<len;i++){
			int carry = value[i]/10;
			value[i] = value[i]%10;
			if(carry>0){
				value[i+1]+=carry;
			}
			
		}
		
		//找到最大位数
		int m = len-1;
		for(;m>=0;m--){
			if(value[m]>0){
				break;
			}
		}
		
		//输出乘积
		for(int i =m;i>=0;i--){
			System.out.print(value[i]);
		}
		
	}

3 约瑟夫杀人法

每数五个人就枪毙第五个人。

	private int TOTALSIZE = 20;
	private int LOOPSIZE = 5;
	public static void main(String[] args) {
		Josephus josephus = new Josephus();
		josephus.killNode();
	}
	private void killNode(){
		Node header = new Node(1);
		Node currentNode  = header;
		
		//构造链表
		for(int i=2;i<=TOTALSIZE;i++){
			currentNode = currentNode.next = new Node(i);
		}
		//收尾相连
		currentNode.next = header;
		
		//说明剩下的不止一个
		while(currentNode!=currentNode.next){
			for(int i=1;i<LOOPSIZE;i++){// 1,2,3,4,5,6
				currentNode = currentNode.next;
			}
			System.out.println("被枪毙的结点为:"+currentNode.next.index);
			currentNode.next = currentNode.next.next;
		}
		
		System.out.println("仅剩下"+currentNode.index);
	}
class Node{
		int index;
		Node next;
		public Node(int index){
			this.index= index;
		}
	}

4 求两个字符串的最长子字符串

public static void main(String[] args) {
		LCSTest lcsTest = new LCSTest();
		lcsTest.getLongestChildrenSize("android", "random");
	}

private void getLongestChildrenSize(String strA, String strB) {
		char[] a = strA.toCharArray();
		char[] b = strB.toCharArray();

		int n = a.length;
		int m = b.length;

		// 矩阵为n行 m列
		int[][] matrix = new int[n][m];

		// 矩阵第一列
		for (int i = 0; i < n; i++) {
			if (a[i] == b[0]) {
				matrix[i][0] = 1;

				for (int j = i + 1; j < n; j++) {
					matrix[j][0] = 1;
				}
				break;
			}

		}

		// 矩阵第一行
		for (int i = 0; i < m; i++) {
			if (a[0] == b[i]) {
				matrix[0][i] = 1;
				
				for(int j=i+1;j<m;j++){
					matrix[0][j] = 1;
				}
				break;
			}
		}
		
		for(int i=1;i<n;i++){
			for(int j=1;j<m;j++){
				if(a[i] == b[j]){
					matrix[i][j] = matrix[i-1][j-1]+1; 
				}else{
					matrix[i][j] = Math.max(matrix[i][j-1], matrix[i-1][j]);
				}
			}
		}
		
		for(int i =0;i<n;i++){
			for(int j=0;j<m;j++){
				System.out.print(matrix[i][j]+" ");
			}
			System.out.println();
		}
		
		

	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值