| 維度 | 二維數組回溯 | 位運算 |
|---|---|---|
| 空間 | O(N²) | O(1) 僅幾個長整型 |
| 衝突檢測 | O(N) 掃描行/列/對角線 | O(1) 位與/或運算 |
| 代碼行數 | ~50 | ~30 |
row:列衝突ld (left diagonal):左下對角線衝突(下一行左移 1 位)rd (right diagonal):右下對角線衝突(下一行右移 1 位)pos = upperlim & ~(row | ld | rd)(upperlim 低 N 位全 1)。p = pos & -pos(隔離 lowest set bit)。test(row|p, (ld|p)<<1, (rd|p)>>1)。#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long sum = 0, upperlim = 1;
void test(long row, long ld, long rd) {
if (row != upperlim) {
long pos = upperlim & ~(row | ld | rd);
while (pos) {
long p = pos & -pos; // 最右可用位
pos -= p; // 移除該位
test(row + p, (ld + p) << 1, (rd + p) >> 1);
}
} else {
++sum; // 找到一解
}
}
int main(int argc, char* argv[]) {
time_t tm = time(0);
int n = (argc > 1) ? atoi(argv[1]) : 16;
if (n < 1 || n > 32) { puts("1-32"); return -1; }
upperlim = (upperlim << n) - 1; // 低 n 位置 1
printf("%d皇后 上限=%ld\n", n, upperlim);
test(0, 0, 0);
printf("共%ld種排列,耗時%d秒\n", sum, (int)(time(0)-tm));
return 0;
}
upperlim = (1<:生成掩碼 0b111...1 (n 個 1)。 pos = upperlim & ~(row|ld|rd):同時排除列、兩條對角線衝突。p = pos & -pos:lowbit 技巧,取最低 1 位(對應最右可用列)。(ld+p)<<1 / (rd+p)>>1:下一行對角線衝突相對當前行左移/右移 1 列。N=13: 73712 解 <0.1s
N=14: 365596 解 ~0.3s
N=15: 2279184 解 ~2s
N=16: 14772512 解 ~14s
位運算版輕鬆解決 N≤16,N=32 理論可行但解數天文級。
在遞歸參數中增加 long sol[32] 記錄每行皇后列位,row==upperlim 時打印。
位運算將 N 皇后的「空間換時間」推向極致:幾個寄存器承載整個棋盤狀態,位級並行完成衝突檢測。這是算法優化中「數據結構位級壓縮」的教科書級範例。