n後問題-回溯法

        n後問題:在n*n的×××上放置n個皇后,按照國際象棋的規則,使其彼此不***。即每兩個皇后之間不處於同一行、同一列、同一對角線。

        首先,行不同可以理解爲第i個皇后必須在第i行,體現在算法中就是當第i個皇后確定位置後,第i+1個皇后必須在第i+1行尋找滿足條件的位置。其次,爲滿足列不同,需要在第i個皇后選擇位置時,判斷位置的行j,是否在之前所有i-1個皇后中沒有相同的行。最後,關於對角線的判斷可以使用對角線的滿足條件i-j=a-b或i+j=a+b來判斷,即要求當前要判斷的位置的行列和差都與之前已確定位置的皇后的行列和差不同。同時滿足上述三個條件才表示第i個皇后的位置是滿足要求的,如果第i個皇后在第i行無法獲得滿足條件的位置,則表示當前i-1個皇后的位置已不會是有效解,在回溯法的解空間樹中,可以剪去該結點,無需遍歷該結點的子結點樹,應當進行回溯。

package test;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by saishangmingzhu on 2018/12/15.
 */
public class EightQueens {
    public static void main(String[] arg){
        new EightQueens().backtracking();
    }

    int n=8;
    int m=8;
    int count=0;
    /**
     * 回溯法
     */
    private void backtracking(){
        int queeni=0;
        int i=0;
        int j=0;
        for (;j<m;j++) {
            int[][] chessboard=new int[m][m];
            //因爲每行只有一個皇后,所有可以使用Map中的key存儲行,value存儲列
            Map<Integer,Integer> queenMap=new HashMap<>();
            chessMoves(queeni, i, j, chessboard,queenMap);
            System.out.println();
        }
    }

    private void chessMoves(int queeni,int i,int j,int[][] chessboard,Map<Integer,Integer> queenMap){
        if (!(judgeRow(i, j,queenMap) == 0 && judgeDiagonal(i, j, queenMap) == 0 ))
            return ;
        chessboard[i][j] = 1;//queeni皇后的位置
        queenMap.put(i,j);
        if (queeni + 1<n) {
            for (int k = 0; k < m; k++) {
                chessMoves(queeni + 1, i + 1, k, chessboard,queenMap);
            }
        } else {
            print(chessboard);
        }
        chessboard[i][j] = 0;
        queenMap.remove(i);
    }

    private void print(int[][] chessboard){
        System.out.println("==="+(++count)+"====");
        for (int i=0;i<m;i++){
            for (int j=0;j<m;j++){
                System.out.print(chessboard[i][j]);
            }
            System.out.println();
        }
    }

    /**
     * 判斷列
     * @param i
     * @param j
     * @param queenMap
     * @return
     */
    private int judgeRow(int i,int j,Map<Integer,Integer> queenMap){
        for (Integer value:queenMap.values()){
            if (value==j){
                return 1;
            }
        }
        return 0;
    }

    /**
     * 判斷對角線
     * @param i
     * @param j
     * @param queenMap
     * @return
     */
    private int judgeDiagonal(int i,int j,Map<Integer,Integer> queenMap){
        for (Integer key:queenMap.keySet()){
            int value=queenMap.get(key);
            if (key-value==i-j || key+value==i+j){
                return 1;
            }
        }
        return 0;
    }
}


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