bzoj 1087

典型使用状态压缩的动态规划。

可以预处理可行的方案来加速。

设f[i][j][k]为第i行,状态为j,共用了k个国王的方案数。

i&(i<<1)=0表示这行方案可行。

i&j=0 && i&(j<<1)=0 && i&(j>>1)=0表示这两种状态不冲突。

#include<cstdio>
bool yes[512][512];
int n,m,cnt,a[512],b[512];
long long ans,f[10][512][82];
bool check(int x){
    return x&(x<<1);
}
bool check(int x,int y){
    return x&y || x&(y<<1) || x&(y>>1);
}
int calc(int x){
    int ans=0;
    for(;x;x>>=1) ans+=x&1;
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<(1<<n);i+=1)
        if(!check(i)) a[++cnt]=i,b[cnt]=calc(i);
    for(int i=1;i<=cnt;i+=1)
        for(int j=1;j<=cnt;j+=1)
            yes[i][j]=check(a[i],a[j]);
    f[0][1][0]=1;
    for(int i=1;i<=n;i+=1)
        for(int j=1;j<=cnt;j+=1)
            for(int k=1;k<=cnt;k+=1) if(!yes[j][k])
                for(int h=b[j]+b[k];h<=m;h+=1)
                    f[i][j][h]+=f[i-1][k][h-b[j]];
    for(int i=1;i<=cnt;i+=1) ans+=f[n][i][m];
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-09-25 15:44  失忆的旅行者  阅读(161)  评论(0编辑  收藏  举报