n皇后问题leetcode-51. N-Queens

   n皇后问题是应用回溯法的经典问题。任一行、列、对角线不能有两皇后并存,因此在判断是否合法时,可以将某一行是否有皇后、某一列是否有皇后分别用数组存起来。注意到,对于往左下右上的对角线,每个点的行号(i)和列号(j)的和相等且与别的对角线不同,因此可用数组将此对角线是否有皇后,即i+j是否为1记录下来,n*n的棋盘有2*n-1条左下到右上的对角线;对于从左上到右下的对角线也类似,每个点的行号(i)和列号(j)的差相等且与别的对角线不同,但是差值可能会出现负值,所以将差值加上n-1,便于用数组记录。

  解决判断是否合法的问题后,就要考虑怎么用回溯法求解了。我的思路是在探测第i行后,如果找到一个可以放置皇后的位置j后,则会递归探测下一行,结束后则会继续探测i行j+1列,故可以找到所有的n皇后的解。

class Solution {
public:
    vector<vector<string>> ans;
    vector<string> res;
    vector<vector<string>> solveNQueens(int n) {
        res = vector<string>(n,string(n,'.'));
        nQueens(0,n);
        return ans;
    }
    void nQueens(int i,int n)
    {//在n*n的棋盘上,第i-1行之前满足条件
        if(i>=n) 
        {
            ans.push_back(res);
            return;
        }
        for(int j=0;j<n;j++)
        {
            res[i][j] = 'Q';
            if(isValid(res,n))
                nQueens(i+1,n);
            res[i][j] = '.';
        }
    }
    bool isValid(vector<string>& sol, int n)
    {//行和列用数组保存,左下的对角线和一样,右下的对角线差一样,且独一无二,也用数组表示
        vector<int> row(n, 0);
        vector<int> col(n, 0);
        vector<int> ldia(2 * n - 1, 0);
        vector<int> rdia(2 * n - 1, 0);
        for (int i = 0; i < sol.size(); i++)
        {
            string str = sol[i];
            for (int j = 0; j < n; j++)
            {
                if (sol[i][j] == 'Q')
                {
                    if (row[i] || col[j] || ldia[i + j] || rdia[i-j+n-1])
                        return false;
                    row[i] = 1; col[j] = 1;
                    ldia[i + j] = 1;  rdia[i-j+n-1] = 1;
                }
            }
        }
        return true;
    }
};
原文地址:https://www.cnblogs.com/tonychen-tobeTopCoder/p/5189775.html