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 }
——现在的努力是为了小时候吹过的牛B!!