LeetCode OJ - N-Queens 回溯法

来源:互联网 发布:淘宝开店相片要求 编辑:程序博客网 时间:2024/06/05 16:41

寻找问题解的一个方法,可以采用列出所有候选解,检查完所有候选解即可得到需要的解。

问题:其中的问题在于,候选解数量很庞大时,采用遍历搜索耗费的时间巨大。

解决:采用不同的筛选方法,减小问题的规模,从而缩短搜索的时间。

方法:回溯法、分支界定法

——————————————————————————————————————————

回溯算法 http://blog.csdn.net/pinkrobin/article/details/5378702

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.总体思路

2.采用什么数据结构

3.需要解决的问题

4.采用什么程序结构

       假设棋盘式NxN的二维数组,首先在第一行放置一个Q,接着在第二行放,直到放到第N行,若放置完成则表示找到一种解决方案。如何遍历所有解决方案呢,可以采用递归的方式,使用深度遍历找出所有方案(调用Q(0))。

        应该采用什么数据结构呢,若采用二维数组Q[N][N],需要解决A.该行是否有元素 B.该列是否有元素 C.该对角线上是否有元素,这几个应该好解决。若现在要在(row, col)这个点上检查是否可以放皇后,row行没还没放故只用判断row行之前的情况,判断如下:

bool flag = false;//不能放置皇后for(i = row-1; i >= 1; i--) {    //每行应该判断三个点:Q[i][col+i-row]、 Q[i][col]、 Q[i][col-i+row]    // 可通过判断行列的变化情况找到这三个点    if( Q[i][col+i-row] == 0 && Q[i][col] == 0 && Q[i][col-i+row] ) {         flag = true;         Q[row][col] = 1;    }}

        如果要记录下所有结果呢,也就是所有的二维表结果,应该怎么设计呢?  因为深度遍历每一次从根节点,访问到叶子节点,本身就是一种解决方案,记录该方案即可。采用输出表示记录该方案。

bool isPutQueen(int row, int col) {   bool flag = false;   for(int i = row - 1; i >= 1; i--) {      if(!Q[i][col+i-row] && !Q[i][col] && !Q[i][col-i+row]) {         flag = true;         break;      }   }   return flag;}void NQueen(int row) {   if(row == N) {      for(int i = 1; i <= N; i++) {         for(int j = 1; j <= N; j++) {            cout << Q[i][j] << " ";            Q[i][j] = 0;         }         cout << endl;      }      cout << endl;      return ;   } else {      for(int i = 1; i <= N; i++) {         for(int j = 1; j <= N; j++)//回溯法的精髓,记录了前面row-1行的情况            Q[row][j] = 0;         if(isPutQueen(row, i)) {            NQueen(row++);         }      }   }}#define N 16int Q[N + 1][N + 1];int main() {    InitQueen();    NQueen(1);    return 0;}

非递归方式:


优化存储结构:

0 0