Bootstrap

dfs——n皇后问题

n皇后问题

 * 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
 * 你的任务是,对于给定的N,求出有多少种合法的放置方法。
 * 
 * Input
 * 共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
 * Output
 * 共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
 * 
 * Sample Input
   * 1
   * 8
   * 5
   * 0
   * 
 * Sample Output
   * 1
   * 92
   * 10

根据n皇后问题,我们可以定义一个长度为n的数组来表示棋盘的行数,数组的值为列数,然后根据回溯法,不用列出所有的情况,每摆出一个棋子就判断它的合法性,不满足的直接返回上一行拜访情况,不用都走完再判断。

for (int lie = 0; lie <a.length ; lie++) {
if (check(a,hang,lie)){
a[hang]=lie;
dfs(a,hang+1);
} }
从第一行开始,一行找一个位置放,这里需要用check函数检查位置是否合法,从第一行到最后一行保证每行只有一个元素,如果不满足的情况下返回,利用回溯的思想,当合法时。利用深搜思想继续从下一行开始判断

if (hang==a.length){
count++;
return;
当每一行都放好一个,行数到最后一行时,count+1,即成功的情况+1

static boolean check(int a[],int h,int l){
for (int i = 0; i <h ; i++) {
if (a[i]= =l){return false;}
if (a[i]+i==h+l){return false;}
if (i-a[i]==h-l){return false;}
}
return true;
}
这里检查位置的合法性要考虑三种情况:
1.判断每一列是否只有一个元素
2判断左对角线是否只有一个元素
3.判断右对角线是否只有一个元素

代码

public class n皇后 {
//static  int []a;
static  int count=0;
//static  int n=0;//

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int a[];
        a=new int[n];
        dfs(a,0);
        System.out.println(count);

    }
   static void dfs(int a[],int hang){
        if (hang==a.length){//不能等于n
            count++;
            return;
        }//应该超出
       for (int lie = 0; lie <a.length ; lie++) {
        if (check(a,hang,lie)){//每一行加一个
            a[hang]=lie;
            dfs(a,hang+1);
        }

       }
   }

   static boolean check(int a[],int h,int l){
       for (int i = 0; i <h ; i++) {
           if (a[i]==l){return false;}
           if (a[i]+i==h+l){return  false;}//左对角线相减为一个数
           if (i-a[i]==h-l){return  false;}//右       加
       }

     return true;
   }
}

;