DFS解决n皇后问题

来源:互联网 发布:金盾网络机柜 编辑:程序博客网 时间:2024/05/18 01:15

问题描述

在nxn格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n皇后问题等价于在nxn格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一类或同一斜线上。

算法设计

用n元组x[1:n]表示n皇后问题的解。其中x[i]表示皇后i放在棋盘的第i行,x[i]列。由于不允许将2个皇后放在同一列,所以解向量中的x[i]互不相同。2个皇后不能放置在同一斜线上市问题的隐约束。将nxn棋盘看作二维方阵,行号从上到下1,2....n,,列号从左到右依次编号为1,2....n。斜率为-1的直线上,两个下标差行号-列号值相等,同理,斜率为+1的斜线上,两个下标的和(行号+列号)值相等。因此只要|i-k|=|j-l|成立,就表明两个皇后位于同一条斜线上,问题的隐约束化成了显约束。

用回溯法解n皇后问题时,用完全n叉树表示解空间。可行性约束place减去不满足行列和斜线约束的子树。

搜索过程代码如下:

import java.util.Scanner;
import java.util.Arrays;
class NQueen    //一个工具类
{
static int n;  //皇后个数
static int []x;//当前解
static long sum;//当前已找到的可行方案数
public static long nQueen(int nn)
{
n=nn;
sum=0;
x=new int[n+1];      //x[0]不用,0下标在计算时比较繁琐,所以从1下标开始用根据棋盘标号。
for (int i=0; i<=n;i++ ) //赋初值0,初始化操作
{
x[i]=0;
}
backtrack(1);
return sum;
}
private static boolean place(int k)//判断当前放置的皇后是否满足条件。与已经搜索到的(k-1)个皇后进行比较
{
for(int j=1;j<k;j++)
if((Math.abs(k-j)==Math.abs(x[j]-x[k]))||(x[j]==x[k]))
return false;                           //不满足条件,则返回false
return true;                                //满足条件返回true
}
private static void backtrack(int t)  //t表示当前搜索的层数,注意该部分的构造
{
if(t>n) 
{
sum++;  
System.out.println(Arrays.toString(x));
}               //t>n表示得到了n皇后的一组放置方法
else
for(int i=1;i<=n;i++)  //对t层上的每个节点进行搜索
{
  x[t]=i;
  if(place(t))backtrack(t+1);


   }


}



}


class NQueenTest
{
public static void main(String[] args) 
{
System.out.print("请输入皇后的个数:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
long result=0;
result=NQueen.nQueen(n);
System.out.println("");
System.out.println("方案数:"+result);
sc.close();




}
}

总结:

1.注意类的建立,该类是一个解决该问题的一个工具类。

2.本题中的搜索过程较为明确,较简单。

3.将判断方法封装在一个成员函数中,符合结构化的设计思想。

4.注意解决问题的过程中,各个参数的确定。数组中保存当前解。

1 0
原创粉丝点击