第九周-八皇后问题


每一行可以而且必须放一个皇后,所以n皇后问题的解可以用一个n元向量X=(x1,x2,.....xn)表示,其中,1≤ i≤ n且1≤ xi≤ n,即第n个皇后放在第i行第xi列上。
由于两个皇后不能放在同一列上,所以,解向量X必须满足的约束条件为:

xi≠ xj;
若两个皇后的摆放位置分别是(i,xi)和(j,xj),在棋盘上斜率为-1的斜线上,满足条件i-j=xi-xj;在棋盘上斜率为1的斜线上,满足条件i+j=xi+xj;
综合两种情况,由于两个皇后不能位于同一斜线上,所以,解向量X必须满足的约束条件为:
|i-xi|≠ |j-xj|

public class Demo {
	static int row;
	static int column;
	static int[] queen = new int[100];
	static char[][] a = new char[100][100];

	static boolean judge(int k)// 判断皇后k放在x[k]列是否发生冲突
	{
		int i;
		for (i = 1; i < k; i++)
			if (queen[k] == queen[i] || Math.abs(k - i) == Math.abs(queen[k] - queen[i])) {
				return false;
			}
		return true;
	}

	public static void mothed(int n) {
		int i, k;
		for (i = 1; i <= n; i++)
			queen[i] = 0;
		k = 1;
		queen[1] = (int) (Math.random() * 8);// 随机第一列的皇后
		while (k >= 1) {
			queen[k] = queen[k] + 1; // 在下一列放置第k个皇后
			while (queen[k] <= n && !judge(k)) {
				queen[k] = queen[k] + 1;// 搜索下一列
			}
			if (queen[k] <= n && k == n){ // 得到一个输出
				return;
			} else if (queen[k] <= n && k < n){
				k = k + 1;// 放置下一个皇后
			}
			else {
				queen[k] = 0;// 重置x[k],进行回溯
				k = k - 1;
			}
		}
	}

	public static void show(int n) {
		int row, column;
		int i;
		for (i=1;i<=n;i++){
			for (int j=0;j<=n;j++)
				a[i][j]=' ';
		}//简单初始化
		for (row = 1, i = 1; row <= n; row++, i++) {
			a[row][queen[i]] = 'Q';
		}
		for (row = 1; row <= n; row++) {
			for (column = 1; column <= n; column++) {
				System.out.print("|"+a[column][row]);
			}
			System.out.println("|");
		}
	}// 输出皇后矩阵

	public static void main(String[] args) {
		int n = 8;
		mothed(n);
		show(n);
	}

}

显示结果:



同理,只需要稍微更改一下源代码,使mothed(int n)函数进行递归。
public class Demo {
	static int temp_0, temp_1, temp_2;
    static int count=0;
	static int[] queen = new int[100];
	static int[][] a = new int[100][100];

	static boolean judge(int k)// 判断皇后k放在x[k]列是否发生冲突
	{
		int i;
		for (i = 1; i < k; i++)
			if (queen[k] == queen[i] || Math.abs(k - i) == Math.abs(queen[k] - queen[i])) {
				return false;
			}
		return true;
	}

	public static void mothed(int n) {
		int i, k;
		for (i = 1; i <= n; i++)
			queen[i] = 0;
		k = 1;
		while (k >= 1) {
			queen[k] = queen[k] + 1; // 在下一列放置第k个皇后
			while (queen[k] <= n && !judge(k)) {
				queen[k] = queen[k] + 1;// 搜索下一列
			}
			if (queen[k] <= n && k == n){ // 得到一个输出
				for (i=1;i<=n;i++){
					System.out.print(queen[i]+" ");
				}
				count++;
				System.out.println("");
			} else if (queen[k] <= n && k < n){
				k = k + 1;// 放置下一个皇后
			}
			else {
				queen[k] = 0;// 重置x[k],进行回溯
				k = k - 1;
			}
		}
	}

	public static void show(int n) {
		int row, column;
		int i;
		for (row = 1, i = 1; row <= n; row++, i++) {
			a[row][queen[i]] = 1;
		}
		for (row = 1; row <= n; row++) {
			for (column = 1; column <= n; column++) {
				System.out.print(a[column][row] + " ");
			}
			System.out.println("");
		}
	}// 输出皇后矩阵

	public static void main(String[] args) {
		int n = 8;
		mothed(n);
		//show(n);
		System.out.println("共"+count+"解决方案。");
	}

}

结果:
1 5 8 6 3 7 2 4 
1 6 8 3 7 4 2 5 
1 7 4 6 8 2 5 3 
1 7 5 8 2 4 6 3 
2 4 6 8 3 1 7 5 
2 5 7 1 3 8 6 4 
2 5 7 4 1 8 6 3 
2 6 1 7 4 8 3 5 
2 6 8 3 1 4 7 5 
2 7 3 6 8 5 1 4 
2 7 5 8 1 4 6 3 
2 8 6 1 3 5 7 4 
3 1 7 5 8 2 4 6 
3 5 2 8 1 7 4 6 
3 5 2 8 6 4 7 1 
3 5 7 1 4 2 8 6 
3 5 8 4 1 7 2 6 
3 6 2 5 8 1 7 4 
3 6 2 7 1 4 8 5 
3 6 2 7 5 1 8 4 
3 6 4 1 8 5 7 2 
3 6 4 2 8 5 7 1 
3 6 8 1 4 7 5 2 
3 6 8 1 5 7 2 4 
3 6 8 2 4 1 7 5 
3 7 2 8 5 1 4 6 
3 7 2 8 6 4 1 5 
3 8 4 7 1 6 2 5 
4 1 5 8 2 7 3 6 
4 1 5 8 6 3 7 2 
4 2 5 8 6 1 3 7 
4 2 7 3 6 8 1 5 
4 2 7 3 6 8 5 1 
4 2 7 5 1 8 6 3 
4 2 8 5 7 1 3 6 
4 2 8 6 1 3 5 7 
4 6 1 5 2 8 3 7 
4 6 8 2 7 1 3 5 
4 6 8 3 1 7 5 2 
4 7 1 8 5 2 6 3 
4 7 3 8 2 5 1 6 
4 7 5 2 6 1 3 8 
4 7 5 3 1 6 8 2 
4 8 1 3 6 2 7 5 
4 8 1 5 7 2 6 3 
4 8 5 3 1 7 2 6 
5 1 4 6 8 2 7 3 
5 1 8 4 2 7 3 6 
5 1 8 6 3 7 2 4 
5 2 4 6 8 3 1 7 
5 2 4 7 3 8 6 1 
5 2 6 1 7 4 8 3 
5 2 8 1 4 7 3 6 
5 3 1 6 8 2 4 7 
5 3 1 7 2 8 6 4 
5 3 8 4 7 1 6 2 
5 7 1 3 8 6 4 2 
5 7 1 4 2 8 6 3 
5 7 2 4 8 1 3 6 
5 7 2 6 3 1 4 8 
5 7 2 6 3 1 8 4 
5 7 4 1 3 8 6 2 
5 8 4 1 3 6 2 7 
5 8 4 1 7 2 6 3 
6 1 5 2 8 3 7 4 
6 2 7 1 3 5 8 4 
6 2 7 1 4 8 5 3 
6 3 1 7 5 8 2 4 
6 3 1 8 4 2 7 5 
6 3 1 8 5 2 4 7 
6 3 5 7 1 4 2 8 
6 3 5 8 1 4 2 7 
6 3 7 2 4 8 1 5 
6 3 7 2 8 5 1 4 
6 3 7 4 1 8 2 5 
6 4 1 5 8 2 7 3 
6 4 2 8 5 7 1 3 
6 4 7 1 3 5 2 8 
6 4 7 1 8 2 5 3 
6 8 2 4 1 7 5 3 
7 1 3 8 6 4 2 5 
7 2 4 1 8 5 3 6 
7 2 6 3 1 4 8 5 
7 3 1 6 8 5 2 4 
7 3 8 2 5 1 6 4 
7 4 2 5 8 1 3 6 
7 4 2 8 6 1 3 5 
7 5 3 1 6 8 2 4 
8 2 4 1 7 5 3 6 
8 2 5 3 1 7 4 6 
8 3 1 6 2 5 7 4 
8 4 1 3 6 2 7 5 
共92解决方案。



八皇后问题是一个古老而著名的问题,是回溯算法的典型案例,由国际西洋棋棋手马克斯·贝瑟尔于1848年提出,即在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,也就是任意两个皇后都不能处于同一行、同一列或同一斜线上,需要求出一共有多少种摆法[^3]。 递归调用在八皇后问题中的应用体现了回溯算法的思想。当取得一个正确解的时候,会把第一个皇后所在位置的所有解先求出来,比如会把(11)这个位置中皇后所有的解求出来。在求解过程中,当到达顶层(找到一种解或者无法继续放置皇后)时,会进行回溯操作。例如,会回到皇后7这里,让它后移一位,然后继续回到皇后8从头遍历看看还有没有合适的解答;假如没有就会回到皇后7继续往后遍历,然后再进入皇后8;都没有之后就会进入皇后6,皇后6遍历后移再进皇后7,直到回溯到皇后1,皇后1后移继续开始最开始的流程往上走,走到头再像之前一样往后走[^1][^2]。 以下是一个Java实现八皇后问题的递归代码示例: ```java public class EightQueens { private static final int N = 8; private int[] queens = new int[N]; private int solutions = 0; public void solve() { placeQueens(0); System.out.println("Total solutions: " + solutions); } private void placeQueens(int row) { if (row == N) { solutions++; return; } for (int col = 0; col < N; col++) { if (isSafe(row, col)) { queens[row] = col; placeQueens(row + 1); } } } private boolean isSafe(int row, int col) { for (int i = 0; i < row; i++) { if (queens[i] == col || Math.abs(queens[i] - col) == Math.abs(i - row)) { return false; } } return true; } public static void main(String[] args) { EightQueens eq = new EightQueens(); eq.solve(); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值