BZOJ1087: [SCOI2005]互不侵犯King
Posted ONION_CYC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1087: [SCOI2005]互不侵犯King相关的知识,希望对你有一定的参考价值。
【算法】状态压缩型DP
【题解】http://www.cnblogs.com/xtx1999/p/4620227.html (orz)
https://www.cnblogs.com/zbtrs/p/6189240.html
dp[i][j][k]为前i行已经放了j个国王并且第i行的状态为k(二进制)的方案数。
状态左移右移预处理两行合法。
dp[i][j][k] = Σdp[i-1][j - num[k]][p]
#include<cstdio> #include<algorithm> using namespace std; const int maxn=10,e2=530; long long f[maxn][e2][maxn*maxn]; int n,mk,num[e2],king[e2],ok[e2][e2]; bool selfcheck(int a) { return !(a&(a>>1)); } int calc(int a) { int cyc=0; while(a) { if(a&1)cyc++; a=a>>1; } return cyc; } bool check(int a,int b) { if((a&b)||(a&(b<<1))||(a&(b>>1)))return 0; return 1; } int main() { scanf("%d%d",&n,&mk); int all=(1<<n)-1,tot=0; for(int i=0;i<=all;i++) { if(selfcheck(i)) { num[++tot]=i; king[tot]=calc(i); //printf("%d\\n",i); } } for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) if(!ok[i][j])if(check(num[i],num[j])) ok[i][j]=ok[j][i]=1;//,printf("%d %d\\n",i,j); f[0][1][0]=1; for(int i=0;i<=n-1;i++) for(int j=1;j<=tot;j++) for(int k=0;k<=mk;k++) if(f[i][j][k]) for(int p=1;p<=tot;p++) if(ok[j][p]&&k+king[p]<=mk) f[i+1][p][k+king[p]]+=f[i][j][k]; long long ans=0; for(int i=1;i<=tot;i++) ans+=f[n][i][mk]; printf("%lld",ans); return 0; }
以上是关于BZOJ1087: [SCOI2005]互不侵犯King的主要内容,如果未能解决你的问题,请参考以下文章