[leetcode] N-Queens II

N-Queens II

Follow up for N-Queens problem.

Now, instead outputting board configurations, return the total number of distinct solutions.

 1 class Solution
 2 {
 3 private:
 4   // 试探算法从最右边的列开始。
 5 void test(long row, long ld, long rd)
 6 {
 7      if (row != upperlim)
 8      {
 9           // row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,
10           // 然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1。
11           // 也就是求取当前哪些列可以放置皇后。
12           long pos = upperlim & ~(row | ld | rd); 
13           while (pos) // 0 -- 皇后没有地方可放,回溯。
14           {
15                // 拷贝pos最右边为1的bit,其余bit置0。
16                // 也就是取得可以放皇后的最右边的列。
17                long p = pos & -pos;                                               
18 
19                // 将pos最右边为1的bit清零。
20                // 也就是为获取下一次的最右可用列使用做准备,
21                // 程序将来会回溯到这个位置继续试探。
22                pos -= p;                            
23 
24                // row + p,将当前列置1,表示记录这次皇后放置的列。
25                // (ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。
26                // (ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。
27                // 此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归
28                // 到一行网格上来解决,所以表示为列的限制就可以了。显然,随着移位
29                // 在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线
30                // 上产生的限制都被记录下来了。 
31                test(row | p, (ld | p) << 1, (rd | p) >> 1);                              
32           }
33      } 
34      else    
35      {
36           // row的所有位都为1,即找到了一个成功的布局,回溯。
37           sum++;
38      }
39 }
40 
41 public:
42   int totalNQueens(int n)
43   {
44     upperlim = 1;
45     sum = 0;
46 
47     upperlim = (upperlim << n) - 1;
48     test(0, 0, 0);
49 
50     return sum;
51   } 
52 private:
53   int upperlim;
54   int sum;
55 };
原文地址:https://www.cnblogs.com/lxd2502/p/4378103.html