n皇后问题
问题描述
如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击
皇后彼此之间会产生攻击是在情况如下:
- 同一行
- 同一列
- 同一斜线上
定义解空间
由题,放置时可以按行的顺序确定列的位置来放置皇后,如四皇后问题,就总共有四个皇后,那么,第一行的皇后可以放在1、2、3、4列,既由根结点往下有四个子结点,接着第二行的皇后同样也有四个选择,则可判断该问题的解空间就是按行的顺序确定列的位置。
确定解空间结构
由上一个解空间的解释可以确定此次的思路是一棵子集树
剪枝函数
用xi表示皇后i放在棋盘的第i行的第xi列, xj表示皇后j放在棋盘的第j行的第xj列。
由于不允许将2个皇后放在同一行所以:i≠j
由于不允许将2个皇后放在同一行所以:xi ≠ xj
由于2个皇后不能放在同一斜线上,即不处于同一正、反对角线,所以:|i-j|≠|xi-xj|
代码实现
package nQueensProblem;
import java.util.Scanner;
public class NQP {
static int n;//皇后个数
static int[] x;//当前解;x[i]表示第i行的皇后i所处的列号
static int sum;//可行解个数
public static int nqueens(int nn) {
n=nn;
x=new int[n+1];
for(int i=0;i<=n;i++) x[i]=0;
sum=0;
backtrack(1);
return sum;
}
public static void backtrack(int t) {
if(t>n) {
sum++;
for(int i=1;i<=n;i++) {
if(i==n)
System.out.println(x[i]);
else
System.out.print(x[i]+" ");
}
}
else {
for(int i=1;i<=n;i++) {
x[t]=i;//是x[t]不是x[i]
if(place(t))
backtrack(t+1);
}
}
}
public static boolean place(int k) {
for(int j=1;j<k;j++) {//是j<k不是j<n
if(x[j]==x[k]||(Math.abs(j-k)==Math.abs(x[j]-x[k])))
return false;
}
return true;
}
public static void main(String[] args) {
System.out.print("请输入皇后的个数:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println("即可行解有以上"+nqueens(n)+"种");
}
}