Java回溯算法求解四皇后问题

回溯算法

基本思路

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

代码格式

private void backtrack("原始参数") {
    // 终止条件(递归必须要有终止条件)
    if ("终止条件") {
        // 一些逻辑操作(可有可无,视情况而定)
        return;
    }

    for (int i = "for循环开始的参数"; i < "for循环结束的参数"; i++) {
        //一些逻辑操作(可有可无,视情况而定)

        //做出选择

        //递归
        backtrack("新的参数");
        //一些逻辑操作(可有可无,视情况而定)

        //撤销操作
    }
}

四皇后问题

其实最经典的是八皇后问题,但是分析起来比较麻烦,所以就通过四皇后来透析一些有关皇后问题,麻雀虽小,五脏俱全嘛。

  • 思路:
    1.指定一个位置
    2.指定第二个位置时,判断该位置是否可放,可放进行下一行,否则回到步骤1
    3.直到最后一行有可放位置

在全局定义一个static int 类型的count变量用于记录有多少中不同的存放类型。

判断该位置是否可存放皇后Q

   /**
     * 判断该位置是否可存放皇后
     * @param queen 数组
     * @param row 行
     * @param col 列
     * @return
     */
    private boolean isVaild(char[][] queen, int row, int col) {

        // 先判断上面是否有没有已经置Q的位置
        for(int i=row-1;i>=0;i--) { //此位置的上面,列不变向上找行
            if(queen[i][col]=='Q') {  //一旦发现
                return false;  //此位置不能放
            }
        }
        // 在判断右上的位置是否有Q
        for(int i=row-1 ,j=col+1;i>=0 &&j<queen[0].length;i--,j++) { //此位置的右上方行要减1,列要加1
            if(queen[i][j]=='Q') {
                return false;
            }
        }
        // 最后判断左上的位置是否有Q
        for(int i =row-1,j=col-1;i>=0&&j>=0;i--,j--) { //此位置的左上方行要减一列也要减一
            if(queen[i][j] =='Q') {
                return false;
            }
        }
        // 如果都没找到,那么说明没有,此位置是可以存放的
        return true;
    }

打印数组

 /**
     * 打印数组
     * @param queen
     */
    private void printQueen(char[][] queen) {
        for(int i = 0 ; i < queen.length ; i ++ ){
            for(int j = 0 ; j < queen.length ; j++){
                System.out.print(queen[i][j]);
            }
            System.out.println();
        }
    }

初始化数组

   /**
     * 初始化数组
     * @param queen
     */
    private void initializeQueen(char[][] queen) {
        for(int i = 0 ; i < queen.length ; i ++ ){
            for(int j = 0 ; j < queen.length ; j++){
                queen[i][j]='A';
            }
        }
    }

回溯算法


    /**
     * 求二维数组中皇后存放方法
     * @param queen 数组
     * @param row 行
     */
    public void queen(char[][] queen, int row) {
        // 结束条件:即当cow为数组的长度时结束
        if (row == queen.length) {
            count++;
          //自己写的一个公共方法,打印二维数组的,
           printQueen(queen);
          System.out.println();
          return;
        }
        for (int col = 0; col < queen.length; col++) {
           //验证当前位置是否可以放皇后
           if (isVaild(queen, row, col)) {
               //如果在当前位置放一个皇后不冲突,就在当前位置放一个皇后
               queen[row][col] = 'Q';
               //递归,在下一行继续……
               queen(queen, row + 1);
               //撤销当前位置的皇后
               queen[row][col] = 'A';
           }
        }
    }
   

main测试

 /**
     * main方法测试
     * @param args
     */
    public static void main(String[] args) {
        char [][] chars = new char[4][4];
        Queen q = new Queen();
        q.initializeQueen(chars);
        q.queen(chars,0);
        System.out.println("总共有:"+count+"种不同的放置方法!");
    }
}

测试结果

AQAA
AAAQ
QAAA
AAQA

AAQA
QAAA
AAAQ
AQAA

总共有:2种不同的放置方法!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值