N_Queen_位运算

目前世界最快的N皇后算法,12皇后解25MS左右

 1 #include <iostream> 
 2 #include <ctime>  
 3 using namespace std;
 4 //sum用来记录皇后放置成功的不同布局数;upperlim用来标记所有列都已经放置好了皇后。  
 5 long sum, upperlim;       
 6    
 7 //试探算法从最右边的列开始。  
 8 void test(long row, long ld, long rd)  
 9      {  
10          if (row != upperlim)  
11              {  
12              // row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,  
13              // 然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1  
14              // 也就是求取当前哪些列可以放置皇后  
15              long pos = upperlim & ~(row | ld | rd);    
16              while (pos)    // 0 -- 皇后没有地方可放,回溯  
17                  {  
18                      // 拷贝pos最右边为1的bit,其余bit置0  
19                      // 也就是取得可以放皇后的最右边的列 
20                      
21                      //long p = pos & -pos;                                                
22                        long p = pos & (~pos + 1);    //按位和补码作与运算 
23                        
24                      // 将pos最右边为1的bit清零  
25                      // 也就是为获取下一次的最右可用列使用做准备,  
26                      // 程序将来会回溯到这个位置继续试探  
27                      pos -= p;
28    
29                      // row + p,将当前列置1,表示记录这次皇后放置的列。  
30                      // (ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。  
31                      // (ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。  
32                      // 此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归  
33                      // 到一行网格上来解决,所以表示为列的限制就可以了。显然,随着移位  
34                      // 在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线  
35                      // 上产生的限制都被记录下来了  
36                      test(row + p, (ld + p) << 1, (rd + p) >> 1);
37                  }  
38              }  
39          else     
40              {  
41              // row的所有位都为1,即找到了一个成功的布局,回溯  
42              sum++;  
43              }  
44 }  
45    
46 int main(int argc, char *argv[])  
47 {
48    time_t start;
49    int n;
50    while(~scanf("%d",&n))
51    
52        {
53             start=clock();
54             sum=0;
55             upperlim=1;
56            // N个皇后只需N位存储,N列中某列有皇后则对应bit置1。  
57            upperlim = (upperlim << n) - 1;    //生成了N个1组成的二进制数       
58            test(0, 0, 0); 
59            printf("Time: %ld Ms\n",clock()-start);
60            printf("ANS of %d Queue is %d\n",n, sum); 
61         }
62     system("pause>nul");
63    return 0;  
64 }

 

posted @ 2013-06-20 15:58  瓶哥  Views(295)  Comments(0Edit  收藏  举报