【LeetCode】51和52.N皇后

  • N皇后

  1. 題目描述

    n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。

    上圖爲 8 皇后問題的一種解法。

    給定一個整數 n,返回所有不同的 n 皇后問題的解決方案。每一種解法包含一個明確的 n 皇后問題的棋子放置方案,該方案中 'Q' 和 '.' 分別代表了皇后和空位。

  2. 思路

    回溯中最經典的問題。這裏簡單總結下回溯的寫法:

    首先,通常需要一個記錄所有滿足條件結果的容器,在下面的代碼中就是參數res;

    其次,需要一個容器來記錄當前回溯的路徑,在下面的代碼中就是參數nQueens;

    最後,就是需要記錄當前搜索的位置,即row;以及終止條件,即n;

    該題目中沒有剪枝條件,但是回溯有時會遇到需要剪枝的情況;

    詳細的理解,請見下方代碼:

  3. C++實現
class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> nQueens(n,string(n,'.')); //n個字符串,每個字符串是n個'.'組成
        solveNQueens(res, nQueens, 0, n);
        return res;
    }
    /**
    res:用於存儲所有的解決方案
    nQueens:用於存儲當前的解決方案
    row:當前解決方案所掃描的行
    n:行/列數
    **/
    void solveNQueens(vector<vector<string>> &res,
                      vector<string> &nQueens,int row,int n){
        if(row==n){//row的合理位置在[0,n-1],當其爲n時表示已經掃描完整個棋盤
            res.push_back(nQueens);
            return;
        }
        for(int col = 0;col<n;col++){
            if(isValid(nQueens,row,col,n)){
                nQueens[row][col] = 'Q'; //放置皇后
                solveNQueens(res, nQueens, row + 1, n);
                nQueens[row][col] = '.'; //還原
            }
        }
    }
    bool isValid(vector<string> &nQueens, int row, int col, int n){
        // 檢查當前列在先前的行中是否已經放置了Q
        for (int i = 0; i<row; ++i)
            if (nQueens[i][col] == 'Q')
                return false;
        // 檢查前面的45度角
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j)
            if (nQueens[i][j] == 'Q')
                return false;
        // 檢查前面的135度角
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j)
            if (nQueens[i][j] == 'Q')
                return false;
        return true;
    }
};

 

  • N皇后II

  1. 題目描述

    類似於上面的題目,只不過變爲返回可能的方案數量,而不是所有的方案。

  2. 思路

    類似於上面的題目,只不過不需要記錄所有的方案,因此不需要res,只使用整型變量count來記錄結果。

  3. C++實現
class Solution {
public:
    int totalNQueens(int n) {
        int count = 0;
        vector<string> nQueens(n,string(n,'.'));
        solveNQueens(count,nQueens,0,n);
        return count;
    }
    // &n?
    void  solveNQueens(int& count,vector<string> nQueens,int row,int n){
        if(row==n){//終止條件
            count++;
            return;
        }
        for(int col=0;col<n;col++){
            if(isValid(nQueens,row,col,n)){
                nQueens[row][col] = 'Q'; // 放置皇后
                solveNQueens(count, nQueens, row + 1, n);
                nQueens[row][col] = '.'; // 還原
            }
        }
    }
    bool isValid(vector<string> &nQueens, int row, int col, int n){
        // 檢查當前列在先前的行中是否已經放置了Q
        for (int i = 0; i<row; ++i)
            if (nQueens[i][col] == 'Q')
                return false;
        // 檢查前面的45度角
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j)
            if (nQueens[i][j] == 'Q')
                return false;
        // 檢查前面的135度角
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j)
            if (nQueens[i][j] == 'Q')
                return false;
        return true;
    }
};

 

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