n皇后问题
-
问题:
请设计一种算法,解决著名的n皇后问题。这里的n皇后问题指在一个n*n的棋盘上放置n个棋子,
使得每行每列和每条对角线上都只有一个棋子,求其摆放的方法数。
给定一个int n,请返回方法数,保证n小于等于15 -
分析:
画图,首先我们在第一行选择一列放入第一个皇后,然后在第二行,选择一列放入一个皇后,放入前需要判断,该列是否和前面的行在题意上冲突,如果冲突则换一列摆放,同意要检查。最终若最后一行能把最后一个皇后放进去则方法数加1。 -
代码(java):
import java.util.Scanner;
/**
* 请设计一种算法,解决著名的n皇后问题。这里的n皇后问题指在一个n*n的棋盘上放置n个棋子,
* 使得每行每列和每条对角线上都只有一个棋子,求其摆放的方法数。
给定一个int n,请返回方法数,保证n小于等于15
*/
public class SelfDo {
static int cnn=0;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int []a=new int [n];
dfs(a,0);//处理第0行,数组下标代表行,值代表列;
System.out.println(cnn);
}
private static void dfs(int[] a, int i) {
if(i==a.length) {
cnn++;
return;
}
for(int k=0;k<a.length;k++) {
if(check(a,i,k)) { //剪枝
a[i]=k;
dfs(a,i+1);
a[i]=0;
}
}
}
private static boolean check(int[] a, int i, int k) {//检查第i行第k列放皇后合不合适
for(int j=0;j<i;j++) { //GG:j<a.length
if(k==a[j]||j-a[j]==i-k||j+a[j]==i+k)//只和已经确定的状态作比较,只比较前态!
return false;
}
return true;
}
- 注意:
- 剪枝(条件判断)是dfs的难点。我们的数组默认值是0,也就是说,数组初始时是把所以的皇后都放在了第一列,因此判断时,一旦把某行在第0列放皇后,则一定会与后面所以值未定的行同出第0列导致判断为false。其实,我们的check函数,也只是用作与前面已经摆放的皇后的位置作比较,以确定当前位置是否可行。
- 如何判断二维数组(i,j)位置的对角线上是否有皇后——找数组下标的规律(位于同一主对角线上的下标横纵坐标之差与i-j之差一致;位于同一副对角线上的下标横纵坐标之和与i+j之和一致。)