Friday, March 6, 2015

N-Queens

N-Queens

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]


--------------------------- thinking ----------------------------------
https://oj.leetcode.com/discuss/13100/accepted-auxillary-space-o-n-using-dfs-cpp
https://oj.leetcode.com/discuss/18411/accepted-java-solution
---------------------------- codes ------------------------------------
class Solution {
public:
    vector<vector<string> > solveNQueens(int n) {
        vector<vector<int>> result;
        vector<int> marker(n, 0);
        puzzleHelper(result, marker, 0, n);
        return cvtResult(result);
    }
    void puzzleHelper(vector<vector<int>> &result, vector<int> &marker, int row, int n) {
        if (row == n) {
            result.push_back(marker);
            return;
        }
        for (int i = 0; i < n; i++) {
            if(isSafe(marker, row, i)) {
                marker[row] = i;
                puzzleHelper(result, marker, row+1, n);
            }
        }
    }
    bool isSafe(vector<int> &marker, int row, int col) {
        for (int cur_row = row - 1, ldia = col - 1, rdia = col + 1; cur_row >= 0; cur_row--, ldia--, rdia++) {
            if (marker[cur_row] == col || marker[cur_row] == ldia || marker[cur_row] == rdia) {
                return false;
            }
        }
        return true;
    }
    vector<vector<string>> cvtResult(vector<vector<int>> &inputs) {
        vector<vector<string>> result;
        for (int i = 0; i < inputs.size(); i++) {
            vector<string> out;
            for (int j = 0; j < inputs[0].size(); j++) {
                string ele;
                for (int index = 0; index < inputs[0].size(); index++) {
                    if (index == inputs[i][j]) {
                        ele += "Q";
                    } else {
                        ele += ".";
                    }
                }
                out.push_back(ele);
            }
            result.push_back(out);
        }
        return result;
    }
};
------------------------------ non recursive codes ---------------------------
class Solution {
public:
    /**
     * Get all distinct N-Queen solutions
     * @param n: The number of queens
     * @return: All distinct solutions
     * For example, A string '...Q' shows a queen on forth position
     */
    vector<vector<string> > solveNQueens(int n) {
        // write your code here
        vector<bool> row(n, true);
        vector<bool> lft_dia(2 * n, true);
        vector<bool> rit_dia(2 * n, true);
        stack<int> rst_stk;
        stack<int> stack;
        stack.push(0);
        vector<vector<int>> result;
        //BUG -> it's very important to have this marker, or the codes will become a dead loop
        vector<bool> visited(n, false);
        while (!stack.empty()) {
            if (stack.size() == (n+1)) {
                stack.pop();
                rst_stk = stack;
                vector<int> result_ind;
                while(!rst_stk.empty()) {
                    int cur_ind = rst_stk.top();
                    rst_stk.pop();
                    result_ind.push_back(cur_ind);
                }
                result.push_back(result_ind);
                int r = stack.top();
                resetLabel(row, lft_dia, rit_dia, r, n-1, n);
                stack.pop();
                visited[n-1] = false;
                stack.push(r+1);
            }
            int r = stack.top();
            int c = stack.size()-1;
            if (r == n) {
                stack.pop();
                if (stack.empty()) break;
                resetLabel(row, lft_dia, rit_dia, stack.top(), stack.size()-1, n);
            } else if (!checkLabel(row, lft_dia, rit_dia, r, c, n) || visited[c]) {
                stack.pop();
                visited[c] = false;
                stack.push(r+1);
            } else {
                setLabel(row, lft_dia, rit_dia, r, c, n);
                visited[c] = true;
                stack.push(0);
            }
        }
        return cvrtResult(result, n);
    }
    void setLabel(vector<bool> &row, vector<bool> &lft_dia, vector<bool>&rit_dia, int r, int c, int n) {
        row[r] = false;
        lft_dia[r+c] = false;
        rit_dia[n+r-c] = false;
    }
    void resetLabel(vector<bool> &row, vector<bool> &lft_dia, vector<bool>&rit_dia, int r, int c, int n) {
        row[r] = true;
        lft_dia[r+c] = true;
        rit_dia[n+r-c] = true;
    }  
    bool checkLabel(vector<bool> &row, vector<bool> &lft_dia, vector<bool>& rit_dia, int r, int c, int n) {
        if (row[r] && lft_dia[r+c] && rit_dia[n+r-c]) {
            return true;
        } else {
            return false;
        }
    }
    vector<vector<string>> cvrtResult(vector<vector<int>> result, int n) {
        vector<vector<string>> output;
        for (int i = 0; i < result.size(); i++) {
            vector<string> rslt;
            for (int j = 0; j < n; j++) {
                string ele(n, '.');
                ele[result[i][j]] = 'Q';
                rslt.push_back(ele);
            }
            output.push_back(rslt);
        }
        return output;
    }
};

No comments:

Post a Comment