Files
2026-06-02 15:56:06 +08:00

102 lines
2.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
int n;
ull ans = 0;
// 每行/每列已经出现过的形状、颜色
int rowShape[4], rowColor[4], colShape[4], colColor[4];
// usedPair[s] 的第 c 位为 1表示 (shape=s, color=c) 已经用过
int usedPair[4];
void dfs(int rem) {
if (rem == 0) {
++ans;
return;
}
// 选择候选数最少的空格子MRV剪枝
int bestIdx = -1;
int bestCnt = 100;
pair<int,int> bestCand[16];
int bestLen = 0;
int tmp = rem;
while (tmp) {
int idx = __builtin_ctz((unsigned)tmp);
int i = idx / n, j = idx % n;
pair<int,int> cand[16];
int len = 0;
for (int s = 0; s < n; ++s) {
if ((rowShape[i] >> s) & 1) continue;
if ((colShape[j] >> s) & 1) continue;
for (int c = 0; c < n; ++c) {
if ((rowColor[i] >> c) & 1) continue;
if ((colColor[j] >> c) & 1) continue;
if ((usedPair[s] >> c) & 1) continue;
cand[len++] = {s, c};
}
}
if (len == 0) return; // 这个格子已经无解,直接剪掉
if (len < bestCnt) {
bestCnt = len;
bestIdx = idx;
bestLen = len;
for (int k = 0; k < len; ++k) bestCand[k] = cand[k];
if (bestCnt == 1) break;
}
tmp &= tmp - 1;
}
int i = bestIdx / n, j = bestIdx % n;
rem ^= (1 << bestIdx);
for (int k = 0; k < bestLen; ++k) {
int s = bestCand[k].first;
int c = bestCand[k].second;
rowShape[i] |= (1 << s);
rowColor[i] |= (1 << c);
colShape[j] |= (1 << s);
colColor[j] |= (1 << c);
usedPair[s] |= (1 << c);
dfs(rem);
usedPair[s] ^= (1 << c);
colColor[j] ^= (1 << c);
colShape[j] ^= (1 << s);
rowColor[i] ^= (1 << c);
rowShape[i] ^= (1 << s);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
if (n == 1) {
cout << 1 << '\n';
return 0;
}
if (n == 2) {
cout << 0 << '\n';
return 0;
}
int rem = (1 << (n * n)) - 1;
dfs(rem);
cout << ans << '\n';
return 0;
}