第二道状压dp...
预处理每种状态j所含1的个数为sum[j]
f[i][j][l]代表第i行,状态为j,当前共有l个国王
枚举本层状态j,上一层状态k,判断八方向是否有相邻:k&j||(k<<1)&j||(k>>1)&j
枚举国王数l,则有f[i][j][l] += f[i-1][k][l-sum[j]]
最后统计f[n][ ][m]即为答案
代码如下
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq using namespace std; const int mod = 1e9; int n,m; long long ans; int a[10],sum[1<<9+5],g[1<<9+5]; long long f[10][1<<9+5][100]; int main() { scanf("%d%d",&n,&m); for(int i = 0; i < (1<<n); i++) { g[i] = (!((i<<1)&i) && !((i>>1)&i)); for(int j = 0; (1<<j) <= i; j++) if((1<<j)&i) sum[i]++; if(g[i]) f[1][i][sum[i]] = 1; } for(int i = 2; i <= n; i++) for(int j = 0; j < (1<<n); j++) { if(!g[j]) continue; for(int k = 0; k < (1<<n); k++) { if(k&j||(k<<1)&j||(k>>1)&j) continue; for(int l = 0; l <= m; l++) f[i][j][l] += f[i-1][k][l-sum[j]]; } } for(int i = 0; i < (1<<n); i++) ans += f[n][i][m]; printf("%lld\n",ans); return 0; }
题外话:
以前总觉得状压dp很难,一直不想写这个东西。写了才发现其实没什么...
只要努力就能克服困难!
原文地址:https://www.cnblogs.com/mogeko/p/11625775.html
时间: 2024-11-05 16:24:24