bzoj 1087
典型使用状态压缩的动态规划。
可以预处理可行的方案来加速。
设f[i][j][k]为第i行,状态为j,共用了k个国王的方案数。
i&(i<<1)=0表示这行方案可行。
i&j=0 && i&(j<<1)=0 && i&(j>>1)=0表示这两种状态不冲突。
#include<cstdio> bool yes[512][512]; int n,m,cnt,a[512],b[512]; long long ans,f[10][512][82]; bool check(int x){ return x&(x<<1); } bool check(int x,int y){ return x&y || x&(y<<1) || x&(y>>1); } int calc(int x){ int ans=0; for(;x;x>>=1) ans+=x&1; return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<(1<<n);i+=1) if(!check(i)) a[++cnt]=i,b[cnt]=calc(i); for(int i=1;i<=cnt;i+=1) for(int j=1;j<=cnt;j+=1) yes[i][j]=check(a[i],a[j]); f[0][1][0]=1; for(int i=1;i<=n;i+=1) for(int j=1;j<=cnt;j+=1) for(int k=1;k<=cnt;k+=1) if(!yes[j][k]) for(int h=b[j]+b[k];h<=m;h+=1) f[i][j][h]+=f[i-1][k][h-b[j]]; for(int i=1;i<=cnt;i+=1) ans+=f[n][i][m]; printf("%lld",ans); return 0; }