回溯法之N皇后问题

问题描述: N皇后问题。在N*N格的棋盘上放置N个皇后,使这些皇后不能互相攻击,即皇后不能在同一行,同一列或者同一对角线上。
解决方法:解决这个问题的最典型的算法就是回溯法。回溯法解题通常包含以下三个步骤:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索;
那么怎么运用回溯法来解决这个问题呢?
1) 首先找出解空间:给棋盘的行和列都编上1到N的号码,皇后也给编上1到N的号码。由于一个皇后应在不同的行上,为不失一般性,可以假定第i个皇后将放在第i行上的某列。因此N皇后问题的解空间可以用一个N元组(X1,X2,…..Xn)来表示,其中Xi是放置皇后i所在的列号。这意味着所有的解都是N元组(1,2,3,…….,N)的置换。解空间大小为N!。
2) 然后我们再找找有什么约束条件。在这里因为解空间已经给我们排除了不在同一行(因为每个皇后分别已经对应不同的行号)的约束条件。我们要判断的是不在同一列和不在同一斜线的约束。因为Xi表示皇后所在的列号,所以如果存在X(t)=X(i)那么肯定存在第k个皇后和第i个皇后同列。所以不同列的判段条件是X(t)!=X(i)。判断是否同一斜线的话,根据基本的数学知识我们可以很容易知道|X(i)-X(t)|=|i-t|就是表示在同一斜线,只要不符合这一条件就行。
下面就是我写的java代码,里面也有很详细的步骤解析
哎呀妈呀这marodown编辑器怎么没有表情可用?。。。
:)

import java.util.Scanner;
//n皇后问题
public class NQueen {
    int N;//n个皇后
    int sum=0;//解决方案数目
    int[] x;//x[i]表示第i行存放皇后的列数为x[i]
    public int countQueen(int n){
        N=n;
        x=new int[N+1];
        backtrack(1);
        return sum;
    }
    public static void main(String[] args) {
        NQueen nq=new NQueen();
        Scanner input=new Scanner(System.in);
        System.out.println("请输入您的皇后数量:");
        int n=input.nextInt();
        System.out.println("解决方案有"+nq.countQueen(n)+"种");
        input.close();
    }
    public void backtrack(int t){
        if(t>N){//遍历到了最后一层,说明这种方法可以
            sum++;
            /*
             * 执行完sum++然后自动返回上一层,检验是否还含有其他可行方案。一步一步地返回
             * 直到第一层,也是一个for()循环遍历每一种可能
             */
        }
        else{
            for(int i=1;i<=N;i++){//第t行有n个可能,也就是说第t个皇后可以存放的有n种可能
                x[t]=i;//一种一种试,不行就下一列
                if(place(t)){
                    backtrack(t+1);
                }
            }
        }
    }
    public boolean place(int col){//此时已经存放好了col-1个皇后,检查现在放的是否跟前面放的皇后有冲突
        for(int i=1;i<col;i++){
            if(Math.abs(col-i)==Math.abs(x[col]-x[i])||x[col]==x[i]){
                return false;
            }
        }
        return true;
    }
}

运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值