• 巧解八皇后问题


     问题描述:

        在8*8的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一个斜线上,文有多少中解法?

    问题分析:

    • 如果用暴力求解发,则时间复杂度为:8*8的棋盘,一共有64个位置,有8为皇后,所以本质是将8位皇后放在64个位置上,即从64个位置中选择8个位置。所以总的搜索空间为:C864。
    • 但是这个问题有很多限制条件,我们将这些限制条件加上之后,就可以大大的降低解空间:
      • 同一行中不能放两个皇后,即每行只能放一个皇后。因此我们可以将8*8的矩阵缩减成一个8维的数组,表示一行只能放置一个皇后,其中数组的值表示:a[i] = j表示第i行在第j列上放置一个皇后;
      • 然后我们需要用3个额外的辅助数组来保存列的放置情况,主对角线的放置情况,次对角线的放置情况:
        • 一共8列,因此用一个8维的boolean型数组记录当前列是否有皇后已经放置;
        • 对角线的问题略有复杂,但是仍然可以分析得出横纵坐标之间的关系:假设在我们放置皇后的数组中,a[3] = 2, 也就是说明:
          • 对于主对角线来说:所有a[1][0], a[2][1], a[4][3], a[5][4], a[6][5], a[7][6]不能再放置皇后,可以发现他们横纵坐标的关系为:x-y=1始终成立,因此我们得出如果a[i] = j, 则所有i-j的位置都不能再放置皇后,而对于8*8的棋盘来说,-7<=x-y<=7, 即-(N-1)<=x-y<=N-1, 即 0<=x-y+N-1 <=2N-2,所以申请一个长度为2N-1的数组来记录主对角线的摆放情况;
          • 对于次对角线来说:所有a[0][5], a[1][4], a[2][3], a[4][1], a[5][0]都不能再放置皇后,可以发现他们横纵坐标的关系为:x+y=5始终成立,因此我们得出如果a[i] = j,则所有i+j的位置都不能再放置皇后,而对于8*8的棋盘来说,0<=x+y<=2N-2,所以申请一个长度为2N-1的数组来记录次对角线的摆放情况。
        • 用深度优先搜索的思路,每次走到一条思路或者终点,需要回溯。所以代码为:递归+回溯。

              

    package com.eight;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    
    class EightQueen {
        private int N; //The number of queens.
        private boolean[] column;
        private boolean[] maind;
        private boolean[] secondaryd;
        private ArrayList<int[]> result = new ArrayList<int[]>();
        
        
        
        /**
         * Initial the column, main diagonal, secondary diagonal to false,
         * which means there is no queen everywhere.
         * @param N
         */
        public void initQ(int N) {
            this.N = N;
            column = new boolean[N];
            maind = new boolean[2 * N - 1];
            secondaryd = new boolean[2 * N - 1];
            int i = 0;
            for(i=0; i<column.length; i++)
                column[i] = false;
            for(i=0; i<maind.length; i++)
                maind[i] = false;
            for(i=0; i<secondaryd.length; i++)
                secondaryd[i] = false;
        }
        
        /**
         * the main function of lay queens.
         */
        public void queens() {
            int[] path = new int[N];
            calcQueen(path, 0);
        }
    
        private void calcQueen(int[] path, int row) {
            // TODO Auto-generated method stub
            if(row == N) {
                result.add(path);
                System.out.println(Arrays.toString(path));
                return;
            }
            for(int col=0; col<N; col++) {
                if(canLay(row, col)) {
                    path[row] = col;
                    column[col] = true;
                    maind[row-col+N-1] = true;
                    secondaryd[row+col] = true;
                    calcQueen(path, row+1);
                    
                    //BackTracking, important!!
                    column[col] = false;
                    maind[row-col+N-1] = false;
                    secondaryd[row+col] = false;
                }
            }
        }
    
        /**
         * Judge if the position can lay a queen.
         * @param row
         * @param col
         * @return
         */
        private boolean canLay(int row, int col) {
            // TODO Auto-generated method stub
            return (!column[col] && !secondaryd[row+col] && !maind[row-col+N-1]);
        }
        
        
        public ArrayList<int[]> getResult() {
            return result;
        }
    }
    
    
    
    public class Queens {
    
        public static void main(String[] args) {
            EightQueen q = new EightQueen();
            q.initQ(8); // It is a eight queens problem.
            q.queens();
            
        }
    
    }
    //Some output instances:
    [0, 4, 7, 5, 2, 6, 1, 3]
    [0, 5, 7, 2, 6, 3, 1, 4]
    [0, 6, 3, 5, 7, 1, 4, 2]
    [0, 6, 4, 7, 1, 3, 5, 2]
    [1, 3, 5, 7, 2, 0, 6, 4]
    [1, 4, 6, 0, 2, 7, 5, 3]
    [1, 4, 6, 3, 0, 7, 5, 2]
    [1, 5, 0, 6, 3, 7, 2, 4]
    [1, 5, 7, 2, 0, 3, 6, 4]
    [1, 6, 2, 5, 7, 4, 0, 3]
    [1, 6, 4, 7, 0, 3, 5, 2]
    [1, 7, 5, 0, 2, 4, 6, 3]
    [2, 0, 6, 4, 7, 1, 3, 5]
  • 相关阅读:
    k3sk8s集群-node节点设置不可调度或者删除node节点
    CentOS8防暴力破解fail2ban
    网站挂马情况处理
    linux给普通用户赋予sudo权限免密码
    Mockito (二十四)
    Mockito (二十三)
    Mockito (二十二)
    Mockito (二十一)
    Mockito (二十)
    Mockito (十九)
  • 原文地址:https://www.cnblogs.com/little-YTMM/p/5478140.html
Copyright © 2020-2023  润新知