回溯_八皇后问题

 嘿嘿:

八皇后问题:

首先要明白规则:

在国际象棋中  一个皇后的攻击范围是 同一行同一列和同一斜线上的所有位置 

我们用回溯来解决这个问题,特别优化了。。。。

四皇后:4*4宫格

 一个字:cao!慢慢理解就行 记住这种思想,,,

第一步:假设在第一行第一列选一个记作为第一个皇后所在位置

然后选下一个  注意攻击范围确定第二个皇后所在位置

此时发现第三个皇后无法再放了 ok:

回溯到第二个皇后位置  让第二个皇后再选一个位置。。。。。。。。

多看几遍 多思考一下,,,,,,

总结:每当一个皇后没有办法存放的时候 回溯到上一个直到回溯到第一个皇后的位置,,,,,,

 八皇后:8*8宫格

 

这个题代码量不大但是回溯那一块比较绕圈  所以要多加总结。。。

 如果当第八行可以成功摆放一个皇后的时候 证明这是一种成功的摆放方式。。。。

 代码细节:

 

 准备操作:

 

 如果处于同一条斜线上

利用斜率来求  两点的斜率是相同的

 为什么结果斜率是1或-1呢?

因为这是宫格 角度是45度  那么斜率是1或者是-1

打印结果:

 源码:

package 刷题.回溯法_N皇后问题;

public class N皇后 {
    public static void main(String[] args) {
        N皇后 leo=new N皇后();
        leo.placeQueens(10);
    }
    private int[] cols;
    //有多少种排法
    int ways;
    private void placeQueens(int n){
        if(n<1){
            return;
        }
        cols=new int[n];
        place(0);
    }
    private void place(int row){
        if(row==cols.length){
            ways++;//次数加一
            return;
        }
        for (int col= 0; col<cols.length;col++) {
            if(isValue(row,col)){
                cols[row]=col;
                place(row+1);
            }
        }
    }
    private boolean isValue(int row,int col){
        for (int i = 0; i <row; i++) {
            if(cols[i]==col){
                return false;
            }
            if((row-i)==Math.abs(cols[i]-col)){
                return false;
            }
        }
        return true;
    }
}

 

回溯算法思想自在打印结果其中;;;; 

八皇后优化:

索引范围: 

左->右对角线:row-col+列数-1

右->左对角线:row+col


存放斜线数组大小:2*行数-1

细节:为什么这里要覆盖?

 因为之前没有会覆盖这里的 我们需要还原现场来把true改变为false

因为true是表示不可以摆

为什么之前没优化的时候 不用覆盖?

因为后面的值会很自然的覆盖前面的  它的覆盖与否和上面的那一种不一样

它不受影响

 优化之后的代码:

package 刷题.回溯法_N皇后问题;


public class N皇后优化 {
    public static void main(String[] args) {
        N皇后优化 leo=new N皇后优化();
        leo.Queenplace(10);
    }
    boolean[] cols;
    boolean[] leftTop;
    boolean[] rightTop;
    int ways;
    private void Queenplace(int n){
        if(n<1){
            return;
        }
        cols=new boolean[n];
        leftTop=new boolean[(n<<1)-1];
        rightTop=new boolean[leftTop.length];
        place(0);
    }
    private void place(int row){
        if(row==cols.length){
            ways++;
            return;
        }
        for (int col= 0; col<cols.length;col++) {
            /**
             * 剪枝
             * 首先只有当条件为真时 才会执行if语句
             */
            if(cols[col]){
                //进来说明 这个位置可存放 说明为空
                continue;
            }
            int leo1=row+col+cols.length-1;
            if(leftTop[leo1]){
                continue;
            }
            int leo2=row-col;
            if(rightTop[leo2]){
                continue;
            }
            cols[col]=true;
            leftTop[leo1]=true;
            rightTop[leo2]=true;
            place(row+1);
            cols[col]=false;
            leftTop[leo1]=false;
            rightTop[leo2]=false;
        }

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值