回溯法解决N后问题(java描述)

版权声明: https://blog.csdn.net/ysdsxry/article/details/78665215

1.问题描述:

N后问题就是在一个N*N的棋盘上放置N个皇后,要求这N个皇后中的任何两个皇后不在同一行或同一列或同一斜线上。

2.算法设计:

使用x[1...n]来表示问题的解。x[i]表示第i个皇后放在棋盘的第i行第x[i]列。因为i是唯一的,所以i是不可能相同的,所以在判断皇后是否能放置时只需要判断当前放置的皇后位置所在的列以及所在的斜线上是否有皇后即可。比较两个皇后x[i],x[j]时,判断它们是否在同一列上可以用x[i]=x[j]是否相等来判断;判断它们是否在同一斜线上可以用|i-j|=|x[i]-x[j]|是否相等来判断(即判断两点之间的斜率是否为1)。

解决N后问题最经典的方法是回溯法,即从第一行第一列开始放置皇后,然后从第二行第一列放置一个皇后判断当前位置能否放置皇后;若不能就判断当前行的当前列的下一列是否能放置皇后,以此类推;如果在一行中所有的列都不能放置皇后,那么就回到上一行放置皇后位置,判断当前放置皇后位置的当前行的下一列。

3.代码实现(java描述)

public class NQueen {
final static int N=8;
final static int queen[]=new int [N];
static int sum=0;
//N皇后问题:在N*N的棋盘上防放置N个棋子,使得所有的棋子都不能在同一行、列、和斜对角线上
//使用一维数组来表示问题的解,x[i]表示在第i行第x[i]列放置皇后

public static void main(String[] args) {
for(int i=0;i<N;i++)
solveQueen(i);
}

//判断当前放置的皇后能否放置
//n表示第i行
static boolean isPlace(int n){
//循环从第一行到当前行的上一行
for(int i=0;i<n;i++){
//只要判断列和斜线不相同就可以了
if(queen[i]==queen[n] || Math.abs(i-n)==Math.abs(queen[i]-queen[n])){
return false;
}
}

return true;
}

//回溯来求N后问题的解
//回溯用递归来解决
//n表当前行是第n行
static void solveQueen(int n){
//对于每一行需要判断当前行的每一列
for(int i=0;i<N;i++){
//放置皇后
queen[n]=i; //循环赋值给列
//如果当前位置可以放置皇后
if(isPlace(n)==true){
//如果是最后一行,那么就输出当前的一个解
if(n==N-1){
//输出解
sum++;
showResult();
}
//如果不是最后一行,并且当前位置可以放置,那么就继续到下一行
else{
solveQueen(n+1); //递归到下一行
}
}
//如果当前行的当前列不能放置,那么就直接循环到下一列,不需要写else
}
}

static void showResult(){
System.out.print("结果"+sum+" ");
for(int i=0;i<N;i++){
System.out.print("("+i+","+queen[i]+")");
System.out.print(" ");
}
System.out.println();
}


}

猜你喜欢

转载自blog.csdn.net/ysdsxry/article/details/78665215