BZOJ 1087 [SCOI2005]互不侵犯King ——状压DP
【题目分析】
沉迷水题,吃枣药丸。
【代码】
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define ll long long int cot[512],c1[512],c2[512][512],n,p; ll dp[10][512][90]; void print(int x) { F(i,0,n-1) printf("%d",(x>>i)&1); } void init() { F(i,0,(1<<n)-1) { int x=i,ret=0; while (x) ret+=x&1,x>>=1; cot[i]=ret; } F(i,0,(1<<n)-1) if ((!((i>>1)&i))&&(!((i<<1)&i))) c1[i]=1; F(i,0,(1<<n)-1) if (c1[i]) F(j,0,(1<<n)-1) if (c1[j]) if ((!((j>>1)&i))&&(!((j<<1)&i))&&(!(j&i))) { // print(i); printf("---> "); print(j); printf("\n"); c2[i][j]=1; } } int main() { scanf("%d%d",&n,&p); init(); F(i,0,(1<<n)-1) if (c1[i]) dp[1][i][cot[i]]=1; F(i,1,n-1) F(j,0,(1<<n)-1) F(k,0,p) F(l,0,(1<<n)-1) if (c2[j][l]) { // printf("dp[%d] ",i+1); print(l); printf(" %d += dp[%d] ",k+cot[l],i); print(j); printf(" %d = %d\n",k,dp[i][j][k]); dp[i+1][l][k+cot[l]]+=dp[i][j][k]; } ll ans=0; F(i,0,(1<<n)-1) ans+=dp[n][i][p]; printf("%lld\n",ans); }