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;
}

 

posted @ 2017-10-30 13:20  或是七一  阅读(102)  评论(0编辑  收藏  举报