八皇后之解

 八皇后問題,是一個古老而著名的問題,是回溯算法的典型例題。該問題是十九世紀著名的數學家高斯1850年提出:在8X8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認爲有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果。計算機發明後,有多種方法可以解決此問題。 

解決八皇后的遞歸思想: 

算法分析:數組a、b、c分別用來標記衝突,a數組代表列衝突,從a[0]~a[7]代表第0列到第7列,如果某列上已經有皇后,則爲1,否則爲0;

  數組b代表主對角線衝突,爲b[i-j+7],即從b[0]~b[14],如果某條主對角線上已經有皇后,則爲1,否則爲0;

  數組c代表從對角線衝突,爲c[i+j],即從c[0]~c[14],如果某條從對角線上已經有皇后,則爲1,否則爲0;

  另優化:第一個皇后在1~4格,最後*2,即爲總解數

class EightQueen{
    //n皇后如何處理?n>=4
    public static int count=0;
    public static int n;
    public static void main(String[] args){
        n=8;
        int[][] board=new int[n][n];
        //0就是空 1就是皇后
        eightQueen(board,0);
    }
    //解決board在第level層的八皇后問題 level 0~7
    public static void eightQueen(int[][] board,int level){
        if(level==n){   //如果遞歸到了第9行 則當前是一個解
            count++;
            System.out.printf("這是第%d個解:\n",count);
            for(int i=0;i<board.length;i++){
                for(int j=0;j<board[i].length;j++){
                    System.out.print(board[i][j]+" ");
                }
                System.out.println();
            }
        }else{
            //1.先做一份上一個情況的備份
            int[][] newBoard=new int[n][n];
            for(int i=0;i<board.length;i++){
                for(int j=0;j<board[i].length;j++){
                    newBoard[i][j]=board[i][j];
                }
            }
            //2.遍歷當前行 找到所有可能的解
            for(int col=0;col<n;col++){
                //3.判斷當前位置是否可以放皇后
                //  3.1 如果可以 則繼續往下一行去尋找
                //  3.2 如果不行 則繼續判斷一下個位置
                if(isNoDanger(newBoard,level,col)){
                    //在賦值皇后之前 先當前行清空
                    for(int c=0;c<n;c++){
                        newBoard[level][c]=0;
                    }
                    newBoard[level][col]=1; //當前給皇后
                    eightQueen(newBoard,level+1);//接着下一行找
                }
            }
        }
    }
    //判斷board當中 x y的位置上是否可以放置一個皇后
    public static boolean isNoDanger(int[][] board,int x,int y){
        //正上
        for(int r=x-1;r>=0;r--){
            if(board[r][y]==1){
                return false;
            }
        }
        //左上
        for(int r=x-1,c=y-1;r>=0&&c>=0;r--,c--){
            if(board[r][c]==1){
                return false;
            }
        }
        //右上
        for(int r=x-1,c=y+1;r>=0&&c<n;r--,c++){
            if(board[r][c]==1){
                return false;
            }
        }
        return true;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章