1. 程式人生 > >【位運算】高效解決n皇後問題

【位運算】高效解決n皇後問題

進行 拷貝 32位 其余 清零 索引 while 運算 code

面向搜索引擎編程

#include<bits/stdc++.h>
 
using namespace std;
 
// sum用來記錄皇後放置成功的不同布局數;upperlim用來標記所有列都已經放置好了皇後。
long sum = 0, upperlim = 1;
// 試探算法從最右邊的列開始。
void test(long col, long ld, long rd)
{
    if (col != upperlim){
        // row,ld,rd進行“或”運算,求得所有可以放置皇後的列,對應位為0,
        // 然後再取反後“與”上全1的數,來求得當前所有可以放置皇後的位置,對應列改為1
        
// 也就是求取當前哪些列可以放置皇後 long pos = upperlim & ~(col | ld | rd); while (pos){ // 拷貝pos最右邊為1的bit,其余bit置0 // 也就是取得可以放皇後的最右邊的列 long p = pos & -pos;//類似樹狀數組中操作,取一個數二進制的最後一個1 // 將pos最右邊為1的bit清零 // 也就是為獲取下一次的最右可用列使用做準備, // 程序將來會回溯到這個位置繼續試探
pos -= p; // row + p,將當前列置1,表示記錄這次皇後放置的列。 // (ld + p) << 1,標記當前皇後左邊相鄰的列不允許下一個皇後放置。 // (ld + p) >> 1,標記當前皇後右邊相鄰的列不允許下一個皇後放置。 // 此處的移位操作實際上是記錄對角線上的限制,只是因為問題都化歸一行網格上來解決,所以表示為列的限制就可以了。 //顯然,隨著移位,在每次選擇列之前進行,原來N×N網格中某個已放置的皇後針對其對角線,上產生的限制都被記錄下來了
test(col + p, (ld + p) << 1, (rd + p) >> 1); } }else{ // row的所有位都為1,即找到了一個成功的布局,回溯 sum++; } } int main() { int n; // 因為整型數的限制,最大只能32位, // 如果想處理N大於32的皇後問題,需要用bitset數據結構進行存儲 scanf("%d",&n); if ((n < 1) || (n > 32)){ printf(" 只能計算1-32之間\n"); exit(-1); } printf("%d 皇後\n", n); // N個皇後只需N位存儲,N列中某列有皇後則對應bit置1。 upperlim = (upperlim << n) - 1; test(0, 0, 0); printf("共有%ld種排列\n", sum); return 0; }

【位運算】高效解決n皇後問題