bzoj 1087: [SCOI2005]互不侵犯King状压dp

Posted lokiii

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1087: [SCOI2005]互不侵犯King状压dp相关的知识,希望对你有一定的参考价值。

显然是状压,设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的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1087: [SCOI2005]互不侵犯King

BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

BZOJ 1087 [SCOI2005]互不侵犯King (状压DP)

BZOJ 1087 [SCOI2005]互不侵犯King

bzoj 1087 [SCOI2005] 互不侵犯King

bzoj 1087: [SCOI2005]互不侵犯King