小国王
来源 : https://www.acwing.com/problem/content/1066/
在 n x n 的棋盘上放 k 个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数。
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define pb push_back
#define PII pair<int, int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 12, M = 1 << N;
vector<int> state;
vector<int> head[M];
int cnt[M];
ll f[N][110][1 << N];
int n, m;
bool check(int x) {
for (int i = 0; i < n; ++i)
if ((x >> i & 1) && (x >> i + 1 & 1)) return false;
return true;
}
int count(int x) {
int res = 0;
for (int i = 0; i < n; ++i) res += x >> i & 1;
return res;
}
int main() {
IO;
cin >> n >> m;
for (int i = 0; i < 1 << n; ++i)
if (check(i)) {
state.pb(i);
cnt[i] = count(i);
}
for (int i = 0; i < state.size(); ++i)
for (int j = 0; j < state.size(); ++j) {
int a = state[i], b = state[j];
if ((a & b) == 0 && check(a | b))
head[i].pb(j);
}
f[0][0][0] = 1;
for (int i = 1; i <= n + 1; ++i)
for (int j = 0; j <= m; ++j)
for (int a = 0; a < state.size(); ++a)
for (int b : head[a]) {
int c = cnt[state[a]];
if (j >= c)
f[i][j][a] += f[i - 1][j - c][b];
}
cout << f[n + 1][m][0] << endl;
return 0;
}