bzoj1087互不侵犯King——状压DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1087
水题...
然而犯了两个致命小错误,调了好半天...详见注释。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int n,m,s[1<<9],cnt,num[1<<9]; bool sid[1<<9][1<<9]; ll f[15][1<<9][90],ans; int cal(int x) { int ret=0; while(x){if(x&1)ret++;x>>=1;} return ret; } void init() { for(int i=0;i<=(1<<n)-1;i++)//别误写成1<<(n-1) ! { if(i&(i>>1))continue; s[++cnt]=i; num[cnt]=cal(i); } for(int i=1;i<=cnt;i++) for(int j=i;j<=cnt;j++)//不是从i+1,因为0和0可以相邻 if((s[i]&s[j])==0&&(s[i]&(s[j]>>1))==0&&(s[i]&(s[j]<<1))==0) sid[i][j]=1,sid[j][i]=1; } int main() { scanf("%d%d",&n,&m); init(); for(int i=1;i<=cnt;i++)f[1][i][num[i]]=1; for(int i=2;i<=n;i++) for(int j=1;j<=cnt;j++) for(int k=1;k<=cnt;k++) if(sid[j][k]) for(int l=num[k];l<=m;l++) { f[i][k][l]+=f[i-1][j][l-num[k]]; // if(f[i-1][j][l-num[k]])printf("i=%d : %d->%d ,l=%d f=%d\n",i,s[j],s[k],l,f[i][k][l]); } for(int i=1;i<=cnt;i++) ans+=f[n][i][m]; printf("%lld",ans); return 0; }