BZOJ 1087 互不侵犯

Posted on 2016-10-31 21:17  ziliuziliu  阅读(111)  评论(0编辑  收藏  举报

方程很好想。转移的话预处理减掉一些废状态。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,kk,f[10][100][1024],top,cnt[1024];
bool vis[1024],map[1024][1024];
long long lowbit(long long x) {return (x&(-x));}
void pre_build()
{
    for (long long i=0;i<=top;i++)
    {
        if (!(i&(i>>1)))
            vis[i]=true;
        for (long long x=i;x;x>>=1)
            if (x&1) cnt[i]++;
    }
    for (long long i=0;i<=top;i++)
    {
        if (!vis[i]) continue;
        for (long long j=0;j<=top;j++)
        {
            if (!vis[j]) continue;
            if ((!(i&j)) && (!(i&(j<<1))) && (!(i&(j>>1))))
                map[i][j]=1;
        }
    }
}
void dp()
{
    for (long long i=0;i<=top;i++) f[1][cnt[i]][i]=1;
    for (long long i=2;i<=n;i++)
        for (long long k=0;k<=top;k++)
        {
            if (!vis[k]) continue;
            for (long long l=0;l<=top;l++)
            {
                if ((!vis[l]) || (!map[l][k])) continue;
                for (long long j=cnt[k];j<=kk;j++)
                    f[i][j][k]+=f[i-1][j-cnt[k]][l];
            }
        }
    long long ans=0;
    for (long long i=0;i<=top;i++)
        ans+=f[n][kk][i];
    printf("%lld\n",ans);
}
int main()
{
    scanf("%lld%lld",&n,&kk);top=(1<<n)-1;
    pre_build();
    dp();
    return 0;
}