回溯算法

回溯算法(back tracking)是一种选优搜索法, 又称试探法, 按选优条件向前搜索, 以达到目标。当探索到某一步时, 发现原先选择并不优或达不到目标, 就退回一步重新选择, 这种走不通就退回再走的技术为回溯法, 而满足回溯条件的某个点称为回溯点

八皇后问题

八皇后问题是一个古老的问题。该问题是十九世纪著名的数学家高斯1850年提出: 在8*8格的国际象棋上摆放8个皇后, 使其不能互相攻击, 即任意两个皇后都不能处于同一行, 同一列或同一斜线上。

八皇后问题解题思路:

问题简化: 将八皇后问题转化为四皇后问题, 并用回溯法来找到它的解

目的: 在4*4棋盘上, 使得4个皇后不能在同行同列以及同斜线上。

Step 1

在棋盘第一个位置放好第一个皇后, 被涂黑的地方不能放皇后

Q1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Step 2 第二行的皇后只能放在第三格或第四格, 比如我们放第三格

Q1

 

 

 

 

 

Q2

 

 

 

 

 

 

 

 

 

Step 3

可以看到再难放下第三个皇后, 此时就要用回溯算法了。我们把第二个皇后更改位置, 此时能放下第三个皇后了

Q1

 

 

 

 

 

 

Q2

 

 

 

 

 

 

 

 

Step 4

虽然是能放置第三个皇后, 但是第四个皇后又无路可走了。返回上层调用(3号皇后), 而3号也别无可去, 继续回溯上层调用(2号), 2号已无路可去, 继续回溯上层(1号), 于是1号皇后改变位置, 继续回溯

 

Q1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

重点看下面这段代码, 这段代码虽短, 但是确是整个算法的核心和灵魂

第一次进来, row=0, 意思是要在第一行摆皇后, 只要传进来的row参数不是8, 表明还没有出结果, 就都不会走if里面的return, 那么就进入到for循环里面, column从0开始, 即第一列。此时第一行第一列肯定符合要求(即check方法肯定通过), 能放下皇后, 因为还没有其他皇后来干扰。

关键是check方法通过了之后, 在if里面又会调用自己, row加了1, 表示摆第二行的皇后。第二行的皇后在走for循环的时候, 分两种情况, 第一种情况: for循环没有走到头就通过check方法了, 这样就继续调用自己, row再加1。第二种情况: for 循环走到头了都没有通过check方法的, 说明第二行根本一个皇后都摆不了, 也触发不了递归, 此时控制第一行皇后位置的for循环column加1, 即第一行的皇后往后移一格, 即摆在第一行第二列的位置上, 然后再往下走, 重复上述逻辑

注意: 一定要添加清零的代码, 它只有在皇后摆不下去的时候会执行清0的动作, 如果皇后摆放很顺利的话是不会走这个清0的动作, 因为已经提前走if里面的return方法结束了。

八个位置太多, 还是按照之前4*4的棋盘, 放4个皇后

第一种放法: 在之前已经聊过, 就不写了, 直接上第二种放法

Step1: 在第一行第二个位置放置第一个皇后

 

Q1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Step2: 在第二行第四列放第二个皇后

 

Q1

 

 

 

 

 

Q2

 

 

 

 

 

 

 

 

 

Step3: 在第三行第一列放置第三个皇后

 

Q1

 

 

 

 

 

Q2

Q3

 

 

 

 

 

 

 

 

Step 4:

 

Q1

 

 

 

 

 

Q2

Q3

 

 

 

 

 

Q4

 

一不小心, 就完成了4*4的棋盘上放置4个皇后

下面是8皇后算法的java版本

public static int[][] arry=new int[8][8];//棋盘,放皇后
public static int map=0;//存储方案结果数量

public static void main(String[] args) {
    // TODO Auto-generated method stub

    System.out.println("八皇后问题");
    findQueen(0);
    System.out.println("八皇后问题共有:"+map+"种可能");
}

public static void findQueen(int i){//寻找皇后节点
    if(i>7){//八皇后的解  
        map++;
        print();//打印八皇后的解
        return;
    }
    
    for(int m=0;m<8;m++){//深度回溯,递归算法
        if(check(i,m)){//检查皇后摆放是否合适
            arry[i][m]=1;
            findQueen(i+1);
            arry[i][m]=0;//清零,以免回溯的时候出现脏数据
            }
    }   
}

public static boolean check(int k,int j){//判断节点是否合适
    for(int i=0;i<8;i++){//检查行列冲突
         if(arry[i][j]==1){
                return false;
         }
    }
    for(int i=k-1,m=j-1; i>=0 && m>=0; i--,m--){//检查左对角线
        if(arry[i][m]==1){
                return false;
        }
    }
    for(int i=k-1,m=j+1; i>=0 && m<=7; i--,m++){//检查右对角线
        if(arry[i][m]==1){
                return false;
        }
    }
    return true;
}

public static void print(){//打印结果
    System.out.print("方案"+map+":"+"\n");
    for(int i=0;i<8;i++){
        for(int m=0;m<8;m++){
            if(arry[i][m]==1){  
                //System.out.print("皇后"+(i+1)+"在第"+i+"行,第"+m+"列\t");
                System.out.print("o ");
            }
            else{
                    System.out.print("+ ");
            }
        }
        System.out.println();
    }
    System.out.println();
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值