Follow up for N-Queens problem.
Now, instead outputting board configurations, return the total number of distinct solutions.
方法一:
我们继续用N-Queens的方法,Time Limit Exceeded,Last executed input:11
int result; void permutationHelper(int* &nums, int index, int n) { if(index == n) { bool flag = true; for(int i = 0; i<n && flag; i++) for(int j=i+1; j<n; j++) if((j-i) == abs(nums[j]-nums[i])) { flag = false; break; } if(flag) result++; } for(int i = index; i < n; i++) { swap(nums[index], nums[i]); permutationHelper(nums, index+1, n); swap(nums[index], nums[i]); } } void permutation(int n) { int* nums = new int[n]; for(int i = 0; i < n; i++) nums[i] = i; permutationHelper(nums,0,n); } int totalNQueens(int n) { // Note: The Solution object is instantiated only once. result = 0; permutation(n); return result; }
long long upperlim; int totalnum; void test(long long row, long long ld, long long rd) { long long pos; long long p; if( row == upperlim) totalnum++; else { pos = upperlim & ~(row | ld | rd); while(pos) { p = pos & (~pos + 1); pos = pos - p; test(row+p, (ld+p)<<1, (rd+p)>>1); } } } int totalNQueens(int n) { // Note: The Solution object is instantiated only once. if(n<1) return 0; totalnum = upperlim = 0; for(int i = 0; i<n; i++) upperlim = upperlim<<1 |1; test(0,0,0); return totalnum; }
我们以6x6的棋盘为例,假设现在已经递归到第四层,前三层放的子已经放好了。row表示已经放的Queen位置,每一个位置用一个1表示。ld表示已经放好的Queen在做对角线上产生的冲突位置。rd表示在右对角线上产生的冲突位置。把它们三个并起来,得到该行所有的禁位,取反后就得到所有可以放的位置(用pos来表示)。pos &(~pos + 1),其结果是取出最右边的那个1。这样,p就表示该行的某个可以放子的位置,把它从pos中移除并递归调用test过程。注意递归调用时三个参数的变化,每个参数都加上了一个禁位,但两个对角线方向的禁位对下一行的影响需要平移一位。最后,如果递归到某个时候发现row=111111了,说明六个皇后全放进去了,解的个数加1。
http://www.matrix67.com/blog/archives/266