[SCOI2005]互不侵犯
Description
Solution
古老的状压DP
\(f[i][j][S]\)表示第i行的状态是S,选了j个国王的方案数,转移方程不难yy出来,滚动一下数组就好了。
emmm...其实这个题可以打表。
Code
#include <cstdio>
const int M = 100;
const int N = 10;
const int B = (1 << 10) + 10;
typedef long long LL;
int tot, n, K;
LL f[2][M][B], s[M], sz[M];
void dfs(int pos, int S, int SZ) {
if (pos >= n) {
if (!(S&(1<<n))) s[++tot] = S, sz[tot] = SZ;
return;
}
if ( pos == 0 || !(S & ( 1 << (pos-1) ) ) ) dfs(pos + 2, S|(1<<pos), SZ+1);
dfs(pos+1, S, SZ);
}
LL dp() {
dfs(0, 0, 0);
f[1][0][0] = 1;
int p = 0;
for (int i = 1; i <= n; ++i, p ^= 1) {
for (int kk = 0; kk <= K; ++kk) {
for (int j = 1; j <= tot; ++j) if (kk + sz[j] <= K) {
LL &S = s[j];
f[p][kk + sz[j]][S] = 0;
for (int k = 1; k <= tot; ++k) {
LL &T = s[k];
if (!(S&T) && !(S&(T<<1)) && !(S&(T>>1))) f[p][kk+sz[j]][S] += f[p^1][kk][T];
}
}
}
}
LL ans = 0;
for (int i = 1; i <= tot; ++i) ans += f[p^1][K][s[i]];
return ans;
}
int main () {
scanf("%d%d", &n, &K);
printf("%lld\n", dp());
}