bzoj 1087: [SCOI2005]互不侵犯King【狀壓dp】
阿新 • • 發佈:2018-07-30
main ace return cst 是否 處理 print const str
顯然是狀壓,設f[i][j][k]為1到i行選j個king,並且第i行狀態為k的方案數,判斷是否可行然後枚舉轉移即可
先把可行狀態預處理出來會變快
#include<iostream> #include<cstdio> using namespace std; const int N=2005; long long n,kk,a[N],sum[N],tot,t,m,f[10][30][1005],ans; bool v[N][N]; int main() { scanf("%lld%lld",&n,&kk); if(kk>(n+1)/2*(n+1)/2) { printf("0"); return 0; } m=(1<<n)-1; for(int i=0;i<=m;i++) if(!(i&(i<<1))) { t=0; for(int j=i;j;j>>=1) t+=(j&1); a[++tot]=i; sum[tot]=t; } for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) if(!(a[i]&a[j])&&!(a[i]&(a[j]<<1))&!((a[i]<<1)&a[j])) v[i][j]=1; for(int i=1;i<=tot;i++) f[1][sum[i]][a[i]]=1ll; for(int i=2;i<=n;i++) for(int j=1;j<=tot;j++) for(int k=1;k<=tot;k++) if(v[j][k]) for(int l=kk;l>=sum[j];l--) f[i][l][a[j]]+=f[i-1][l-sum[j]][a[k]]; for(int i=1;i<=tot;i++) ans+=f[n][kk][a[i]]; printf("%lld",ans); return 0; }
bzoj 1087: [SCOI2005]互不侵犯King【狀壓dp】