bzoj 1087
状态压缩DP。
假设一个二进制数1001,1就表示在这个位置放一个国王,0就表示不在这个位置放一个国王。
就可以保存每一行的状态了。
可以先预处理所有的单行可行状态,这样会快一点。
用位运算来判断是否可行。
设这一行状态为i,前一行状态为j。
i&(i>>1)=0就表示这一行不会有冲突。
i&(j>>1)=0 && i&j=0 && i&(j<<1)=0就表示这两行不会互相冲突。
#include<cstdio> int n,k,m,a[512],g[512],y[512][512]; long long ans,f[10][512][82]; int calc(int x){ int ans=0; while(x) ans+=x&1,x>>=1; return ans; } int main(){ scanf("%d%d",&n,&k); for(int i=0;i<(1<<n);i+=1) if(!(i&(i>>1))) a[++m]=i,g[m]=calc(i); for(int i=1;i<=m;i+=1) for(int j=i;j<=m;j+=1) if(!(a[i]&a[j]) && !(a[i]&(a[j]<<1)) && !(a[i]&(a[j]>>1))) y[i][j]=y[j][i]=1; f[0][1][0]=1; for(int i=1;i<=n;i+=1) for(int j=1;j<=m;j+=1) for(int p=1;p<=m;p+=1) if(y[j][p]) for(int v=g[j]+g[p];v<=k;v+=1) f[i][j][v]+=f[i-1][p][v-g[j]]; for(int i=1;i<=m;i+=1) ans+=f[n][i][k]; printf("%lld",ans); return 0; }