1. 程式人生 > >[LeetCode] N皇後問題

[LeetCode] N皇後問題

操作 -i cnblogs n) 執行 total class != image

LeetCode上面關於N皇後有兩道題目:
51 N-Queens:https://leetcode.com/problems/n-queens/description/

52 N-Queens II:https://leetcode.com/problems/n-queens-ii/description/

兩道題目其實差不多,一題是只要返回解的個數就可以了,一題是返回所有的解,做起來一模一樣。

什麽是N皇後問題?我們需要在一個N*N的棋盤上,放置N個皇後,使這些皇後不能互相攻擊(即兩個皇後之間不能處於同一行、同一列或者是同一斜線上),我們要求滿足這個條件的所有解。

我采用的是回溯法去解決N皇後問題:

我們先在第一列放置一個皇後,然後在第二列與第一列不沖突的位置再放皇後,在第三列與第一列、第二列不沖突的位置放皇後……執行這樣的操作,一直到第N列,我們就得到一個解了。

怎麽回溯呢?我們可以想象成一棵樹。假設我們在第一列的第一行放置了皇後,然後遞歸模擬了所有情況後,把第一列的第一行的皇後放到第二行,繼續遞歸模擬所有情況。一直到把所有解都得出來。

下面看看LeetCode的具體題目:

51 N-Queens:

題目:

技術分享圖片

代碼:

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> queens(n);
        
for (int i = 0; i < n; i++) { queens[i] = ""; for (int j = 0; j < n; j++) { queens[i] += "."; } } helper(res, queens, 0, n); return res; } void helper(vector<vector<string>> &res, vector<string> queens, int
j, int n) { if (j == n) { res.push_back(queens); return; } for (int i = 0; i < n; i++) { if (isValid(queens, i, j)) { queens[i][j] = Q; helper(res, queens, j + 1, n); queens[i][j] = .; } } } bool isValid(vector<string> s, int i, int j) { for (int k = 0; k < s.size(); k++) { if (i != k && s[k][j] == Q) return false; } for (int k = 0; k < s.size(); k++) { if (j != k && s[i][k] == Q) return false; } for (int m = i + 1, n = j + 1; m < s.size() && n < s.size(); m++, n++) { if (s[m][n] == Q) return false; } for (int m = i + 1, n = j - 1; m < s.size() && n >= 0; m++, n--) { if (s[m][n] == Q) return false; } for (int m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) { if (s[m][n] == Q) return false; } for (int m = i - 1, n = j + 1; m >= 0 && n < s.size(); m--, n++) { if (s[m][n] == Q) return false; } return true; } };

52 N-Queens II:

題目:

技術分享圖片

代碼:

class Solution {
public:
    int totalNQueens(int n) {
        vector<string> queens(n);
        for (int i = 0; i < n; i++) {
            queens[i] = "";
            for (int j = 0; j < n; j++) {
                queens[i] += 0;
            } 
        }
        int res = 0;
        helper(res, queens, 0, n);
        return res;
    }
    void helper(int &res, vector<string> queens, int j, int n) {
        if (j == n) {
            res++;
            return;
        }
        for (int i = 0; i < n; i++) {
            if (isValid(queens, i, j)) {
                queens[i][j] = 1;
                helper(res, queens, j + 1, n);
                queens[i][j] = 0;
            }
        }
    } 
    bool isValid(vector<string> queens, int i, int j) {
        for (int k = 0; k < queens.size(); k++) {
            if (queens[i][k] == 1 && k != j) return false; 
        }
        for (int k = 0; k < queens.size(); k++) {
            if (queens[k][j] == 1 && k != i) return false; 
        }
        for (int m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
            if (queens[m][n] == 1) return false;
        }
        for (int m = i + 1, n = j - 1; m < queens.size() && n >= 0; m++, n--) {
            if (queens[m][n] == 1) return false;
        }
        for (int m = i - 1, n = j + 1; m >= 0 && n < queens.size(); m--, n++) {
            if (queens[m][n] == 1) return false;
        }
        for (int m = i + 1, n = j + 1; m < queens.size() && n < queens.size(); m++, n++) {
            if (queens[m][n] == 1) return false;
        }
        return true;
    }
};

除了原來的函數,我們用到了一個用於回溯的helper函數,一個用於檢測當前位置是否可放置皇後的函數。

[LeetCode] N皇後問題