n皇后问题

 首先,可归纳问题的条件为,n皇后之间需满足:

           1.不在同一行上

           2.不在同一列上

           3.不在同一斜线上

           4.不在同一反斜线上


输入:4

输出:第1种摆法
          + + Q + 
          Q + + + 
          + + + Q 
          + Q + + 

          第2种摆法
          + Q + + 
          + + + Q 
          Q + + + 
          + + Q + 

4皇后问题共有2种摆法


这大段我从别人博客摘抄下来的:

 这为我们提供一种遍历的思路,我们可以逐行或者逐列来进行可行摆放方案的遍历,每一行(或列)遍历出一个符合条件的位置,接着就到下一行或列遍历下一个棋子的合适位置,这种遍历思路可以保证我们遍历过程中有一个条件是绝对符合的——就是下一个棋子的摆放位置与前面的棋子不在同一行(或列)。接下来,我们只要判断当前位置是否还符合其他条件,如果符合,就遍历下一行(或列)所有位置,看看是否继续有符合条件的位置,以此类推,如果某一个行(或列)的所有位置都不合适,就返回上一行(或列)继续该行(或列)的其他位置遍历,当我们顺利遍历到最后一行(或列),且有符合条件的位置时,就是一个可行的8皇后摆放方案,累加一次八皇后可行方案的个数,然后继续遍历该行其他位置是否有合适的,如果没有,则返回上一行,遍历该行其他位置,依此下去。这样一个过程下来,我们就可以得出所有符合条件的8皇后摆放方案了。这是一个深度优先遍历的过程,同时也是经典的递归思路。

      接下来,我们以逐列遍历,具体到代码,进一步说明。首先,从第一列开始找第一颗棋子的合适位置,我们知道,此时第一列的任何一个位置都是合适的,当棋子找到第一个合适的位置后,就开始到下一列考虑下一个合适的位置,此时,第二列的第一行及第二行显然就不能放第二颗棋子了,因为其与第一个棋子一个同在一行,一个同在一条斜线上。第二列第三行成为第二列第一个合适的位置,以此类推,第三列的第5行又会是一个合适位置,这个过程中,我们注意到,每一列的合适位置都是受到前面几列的位置所影响,归纳如下:

      假设前面1列的棋子放在第3行,那当前列不能放的位置就一定是3行,2行,4行。因为如果放在这三行上就分别跟前一列的棋子同在一行、同在斜线、同在反斜线上,不符合我们的要求。


这是我对这段代码的解读(不一定对-_-!):

public class Main {

	public static int num = 0;// 方案数
	public static int maxQueen;// 皇后数;棋盘的行数、列数
	public static int[] cols; // 棋盘的列
	// cols[x]=y的意思是:第x列的皇后在第y行(一列只能有一个皇后)

	public static void arrange(int n) {// n代表当前摆到第n列;或者可以说是摆到第n列皇后
		boolean[] rows = new boolean[maxQueen];// 棋盘的行,true是不合法
		for (int i = 0; i < n; i++) {// 遍历第n列之前的列
			rows[cols[i]] = true;// 第i列皇后所在的那一行是不合法的
			int d = n - i; // 不明白这个d代表了什么-_-!
			if (cols[i] - d >= 0)// 判断是否超界
				// 第i列皇后的主对角线(皇后的右下角那个格)是不合法的
				rows[cols[i] - d] = true;
			if (cols[i] + d <= maxQueen - 1)// 判断是否超界
				// 第i列皇后的副对角(皇后的左上角那个格)线是不合法的
				rows[cols[i] + d] = true;
		}
		for (int i = 0; i < maxQueen; i++) {
			if (rows[i])// 判断当前列中的该行是否合法,true是不合法
				continue;
			cols[n] = i;// 当前列的皇后所在行数为i
			if (n < maxQueen - 1)// 当前列不是最后一列时
				arrange(n + 1);
			else { // 当前列是最后一列时
				num++;
				print();
			}
		}
	}// 如果当当前列中所有行都不合法时,会回溯到上一个方法

	public static void print() {
		System.out.println("第" + num + "种摆法");
		for (int i = 0; i < maxQueen; i++) {
			for (int j = 0; j < maxQueen; j++) {
				if (i == cols[j])
					System.out.print("Q ");// 皇后
				else
					System.out.print("+ ");
			}
			System.out.println();
		}
		System.out.println();
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		maxQueen = in.nextInt();
		cols = new int[maxQueen];
		arrange(0);
		System.out.println(maxQueen + "皇后问题共有" + num + "种摆法");
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值