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.."]
]


思路:回溯或者二进制法

思路很清晰,首先我是每行插入一个,所以行的问题不需要考虑,然后就是需要判断列和两个对角线的问题。判断的程序是一个难题:主要就是八个位判断

1<<colIndex  代表第几列的时候,向左移位colIndex位,如果有效(此时为0),此时就要setFlag,并操作,因为,我刚刚就是已经有代表哪几个位已经占据的标志了。至于后面的unsetFlag函数,只是通过某种数学逻辑关系进行运算,返回原来的状态。colFlag&~(1<<colIndex)。

在真正的主程序里面,首先定义rowIndex为answer的数组,一旦满了,就保存进堆栈。因为最大只能到n-1的。

首先在answer放入n个’.',然后从0到n-1 开始遍历,先是判断是否满足,不满足直接return,满足,开始更新各个flag值,此时answer已经存入一组数,满足了,可以存入堆栈,然后开始下一层,这个时候,还是从0开始一个个判断,发现,总有不能满足的。继续下一个i值。

值得注意的是,每个循环里面,在加入q之后,为了下一列的判断,还得出栈,退出q,不然程序出错。

answer的进栈和出栈也是对称的。总之,回溯法是对称的。


代码:

class Solution {
private:
    int colFlag;//代表列
    int diagFlag1;//index=i+j
    int diagFlag2;//index=n-1+i-j
    
    bool isValid(int rowIndex,int colIndex,int n){
        //行不需要判断,因为我是按照行走的
        //为0说明有效
        if( (1<<colIndex)&colFlag ){
            //为1 无效
            return false;
        }
        if( (1<<(rowIndex+colIndex))&diagFlag1  ){
            return false;
        }
        if( (1<<(n-1+rowIndex-colIndex) ) & diagFlag2 ){
            return false;
        }
        return true;
    }
    
    void setFlag(int rowIndex,int colIndex,int n){
        colFlag   |=(1<<colIndex);
        diagFlag1 |=(1<<(rowIndex+colIndex));
        diagFlag2 |=(1<<(n-1+rowIndex-colIndex));
    }
    
    
    void unsetFlag(int rowIndex, int colIndex, int n) {
        colFlag &= ~(1 << colIndex);
        diagFlag1 &= ~(1 << (rowIndex + colIndex));
        diagFlag2 &= ~(1 << (n + rowIndex - colIndex - 1));
    }
    
    void queenHelper(int n, vector<string> &answer, vector<vector<string> > &result) {
        int rowIndex = answer.size();

        if (rowIndex == n) {
            result.push_back(answer);
            return;
        }
        
        answer.push_back(string(n, '.'));
        for (int i = 0; i < n; i++) {
            if (isValid(rowIndex, i, n)) {
                setFlag(rowIndex, i, n);
                answer.back()[i] = 'Q';
                queenHelper(n, answer, result);
                answer.back()[i] = '.';
                unsetFlag(rowIndex, i, n);
            }
        }
        answer.pop_back();
    }

public:
    vector<vector<string> > solveNQueens(int n) {
        // https://oj.leetcode.com/problems/n-queens/

        colFlag = diagFlag1 = diagFlag2 = 0;
        vector<vector<string> > result;
        vector<string> answer;

        queenHelper(n, answer, result);
        return result;
    }
};


posted @ 2015-10-07 07:44  JSRGFJZ6  阅读(120)  评论(0编辑  收藏  举报