递归算法解决八皇后问题

在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有 76 种方案。1854 年在柏林的象棋杂志上不同的作者发表了 40 种不同的解,后来有人用图论的方法解出 92 种结果。(这个问题也一共有92种解法)
思路分析

  1. 第一个皇后放置在第一行第一列
  2. 第二个皇后放置在第二行第一列,判断是否满足条件,如果不满足,继续放置在第三列、第四列,直到满足条件为止
  3. 继续放置后面的皇后,直到所有皇后放置的地方均满足条件
  4. 当得到一个正确的解之后,最后得到正解的栈会退回到上一个栈,此时开始进行回溯,直到将第一个皇后放置在第一列的所有正解全部得到
  5. 然后回头继续将第一个皇后放置在第一行第二列,后面开始循环步骤1,2,3,4。直到所有的解全部得到,所有的解包括,将第一个皇后放置在第三列、第四列直到第八列后面的皇后所有摆放均满足条件
    这里说明一下,这里八皇后摆放是在一个棋盘上进行,理论上应该创建一个二维数组,但是通过算法,以为数组即可解决问题。
    例子:八皇后中,用一维数组解决,其中有一个解为arr[8]={0,4,7,5,2,6,1,3},在这里arr[i]=value表示第i+1个皇后放在第i+1行的第value+1列即arr[0]=1表示第1个皇后在第1行的第1列;arr[1]=4表示第2个皇后在第2行的第5列。
    接下来是代码部分
public class Queue8 {
	static int count;
	// 一般都是用二维数组来表示棋盘的行和列,但是在本题中八皇后本身就可以表示行,比如第一个皇后可以用0来表示
	// 比如,在八皇后问题的92种解法有一个摆放的位置是{0,4,7,5,2,6,1,3},这里arr[0]=0就表示第一个皇后在第一行第一列的位置,
	// arr[1]=4表示第二个皇后摆放的位置是在第二行的第5列,也就是说皇后最后的位置用一维数组表示即为:arr[i]=val,表示第i+1个皇后
	// 放在第i+1行的第val+1列上
	int[] arr = new int[8];
	int max = 8;

	// 先写一个打印的方法,将皇后摆放的位置打印出来,同时,没打印一个结果就将count++,最后显示count有多少种解法
	public void print() {
		count++;
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + "  ");
		}
		System.out.println();
	}

	// 写一个摆放皇后的方法
	public void put(int n) {
		if (n == max) {	//n=8时,八个皇后就放置好
			print();
			return;
		}
		//这里将第一个皇后在第一列所有正解全部得到后,就开始回溯,摆放第一个皇后在第二列的所有正解。比如说第一个皇后的在第一列
		//的所有正解摆放完毕,递归就会向上一层开始回溯,直到回溯到最开始的循环部分,然后继续走循环,i+1(将皇后放在后一个位置)
		//然后又开始进行递归,直到退出最开始的大循环,就代表所有正解全部得到
		for (int i = 0; i < max; i++) {	
			// 先将皇后放在该行的第一列,也就是(n,0)的位置,因为最后测试的时候第一个皇后为0,所以n可以直接表示二维数组的行数
			arr[n] = i;
			// 然后判断该皇后摆放的位置是否满足题目规则,写一个方法判断
			// 如果皇后摆放的位置冲突,则继续循环将皇后摆放在该行的下一列,直到位置不冲突为止;如果摆放的位置不冲突,递归继续摆放下一个皇后
			if (judge(n)) {
				put(n + 1);
			}
		}
	}
	// 八皇后的问题是将8的皇后的棋子摆在棋盘上,每个皇后不能在同一行同一列以及同一个对角线上,所以写一个方法来判断
	// 第n个皇后的位置和前面n-1个皇后的位置受否冲突
	public boolean judge(int n) {
		for (int i = 0; i < n; i++) {
			// arr[i] == arr[n]判断所有皇后是否在同一列
			// Math.abs(n - i) == Math.abs(arr[n] - arr[i]判断所有皇后是否在同一斜线
			if (arr[i] == arr[n] || Math.abs(n - i) == Math.abs(arr[n] - arr[i])) {
				return false;
			}
		}
		return true;
	}
	// 主方法测试
	public static void main(String[] args) {
		Queue8 queue8 = new Queue8();
		queue8.put(0);// 从第一个皇后开始摆放
		System.out.println("一共有" + count + "种解法");

	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值