d757: 11195 - Another n-Queen Problem

Tags: 8-queen, bitmask, performance


出處:https://zerojudge.tw/ShowProblem?problemid=d757
提交:https://zerojudge.tw/Submissions?problemid=d757&account=allllllan123456


問題:給你許多個正整數 $N\in[4,14]$,每個正整數會對應到一個棋盤的邊長,對於每個棋盤我們都限制有些位置不能放置皇后,那請問每個棋盤分別有多少種擺放 $N$ 皇后的方法。


解法:這題如果用傳統的 DFS 試誤法應該也是會過,但是我想說既然我已經過了極致加速版的 d543,那不如就直接改那題的 code 吧!我們可以把題目輸入的每個 row 的限制點轉成一個 bitmask 稱為 full[i],那麼限制點就是那些 full[i] 的 0-bits。第 9 行的 for loop 一開始的 ava 用 full[row]& 就能先行把限制點去除,另外第 8 行斷定擺放完畢的條件也不再是看 col 有沒有放滿,因為有限制點的緣故,只要確定每個 row 都考慮過後就能算是一種了。


 1#include <bits/stdc++.h>
 2using namespace std;
 3
 4int n, counter;
 5unsigned full[14];
 6
 7void dfs(unsigned row, unsigned col, unsigned diag1, unsigned diag2) {
 8	if (row == n) counter++;
 9	for (unsigned ava=full[row]&~(col|diag1|diag2), now=ava&-ava; // now is the current position to be placed.
10        ava; ava^=now, now=ava&-ava) // ava is short for available columns.
11        dfs(row+1, col|now, (diag1|now)<<1, (diag2|now)>>1);
12}
13
14int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); // IO 優化
15	for (int t=1; cin >> n && n; t++) {
16        memset(full, 0, sizeof full);
17        for (int i=0; i<n; i++) {
18            char str[15]; cin >> str;
19            for (int j=0; j<n; j++) {
20                full[i] <<= 1;
21                if (str[j] == '.') full[i] |= 1;
22            }
23        }
24        counter=0, dfs(0, 0, 0, 0), cout << "Case " << t << ": " << counter << '\n';
25    }
26    return 0;
27}

no image