n皇后问题(回溯与dfs)

问题描述:

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
hdu 网站直达

经典回溯法(非递归):

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

//经典算法:n皇后问题
//回溯法
public class TestNQueen {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        solveNQueens(n);

    }

    static int[] a;//存储皇后的位置--a[0]=1表示第一行第二列(0,1)位置有一个皇后
    private static void solveNQueens(int n) {
        // TODO Auto-generated method stub
        init(n);//初始化棋盘
        int i=0,j=0,k=0;
        while(i<n){
            while(j<n){
                a[i] = j;
                if(valid(i)){
                    j=0;//找下一行的第一列做比较
                    break;
                }else{
                    a[i] = -1;
                    ++j;//比较这一行的下一列
                }
            }
            if(a[i]==-1){//如果该行未被放置皇后
                if(i==0){
                    break;//此刻已经回溯到第一行
                }else{
                    --i;//回溯
                    j=a[i]+1;//比较上一行的下一列
                    a[i]=-1;
                    continue;
                }
            }
            if(i==n-1){ //表示已经找到最后一行
                System.out.println("解法"+(++k)+":");
//              list.add(print());//打印
                print();
                --i;//回溯
                j=a[i]+1;//比较上一行的下一列
                a[i]=-1;
                continue;
            }
            i++;
        }

//      return list;
    }

    //打印n皇后
    private static void print() {
        // TODO Auto-generated method stub
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+" ");  //观察a[]数组的元素值
        }
        System.out.println();
        System.out.println("-----以下是皇后的位置----");
//      List<String> list = new ArrayList<String>();
        for(int i=0;i<a.length;i++){
            for(int j=0;j<a.length;j++){
                if(a[i]!=j){
                    System.out.print(". ");
//                  list.add(".");
                }else{
                    System.out.print("Q ");
//                  list.add("Q");
                }
            }
            System.out.println();
        }
        System.out.println();

//      return list;
    }

    //判断(i,j)位置是否合法
    private static boolean valid(int i) {
        // TODO Auto-generated method stub
        for(int k=0;k<i;k++){
            if( a[i] == a[k] || Math.abs(i-k) == Math.abs(a[i]-a[k])){
                return false;
            }
        }

        return true;
    }

    private static void init(int n) {
        // TODO Auto-generated method stub
        a = new int[n];
        for(int i=0;i<n;i++){
            a[i] = -1; // i对应行,a[i]对应列
        }

    }

}

DFS解法:

import java.util.Scanner;

//经典算法:n皇后问题
//dfs解法
public class TestNQueen {


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        init(n);
        solveNQueensII(0,n);

    }

    static int num=0;
    private static void solveNQueensII(int k,int n){

        if(k==n){
            num++;
//          print();
            return;
        }else{
            for(int i=0;i<n;i++){
                a[k] = i;
                if(valid(k)){//判断该位置是否合法
                    solveNQueensII(k+1,n);
                }
            }
        }
    }

    private static void init(int n) {
        // TODO Auto-generated method stub
        a = new int[n];
        for(int i=0;i<n;i++){
            a[i] = -1; // i对应行,a[i]对应列
        }
    }
    //判断(i,j)位置是否合法
    private static boolean valid(int i) {
        // TODO Auto-generated method stub
        for(int k=0;k<i;k++){
            if( a[i] == a[k] || Math.abs(i-k) == Math.abs(a[i]-a[k])){
                return false;
            }
        }
        return true;
    }

 }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值