bzoj1087互不侵犯King——状压DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1087

水题...

然而犯了两个致命小错误,调了好半天...详见注释。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m,s[1<<9],cnt,num[1<<9];
bool sid[1<<9][1<<9];
ll f[15][1<<9][90],ans;
int cal(int x)
{
    int ret=0;
    while(x){if(x&1)ret++;x>>=1;}
    return ret;
}
void init()
{
    for(int i=0;i<=(1<<n)-1;i++)//别误写成1<<(n-1) ! 
    {
        if(i&(i>>1))continue;
        s[++cnt]=i;
        num[cnt]=cal(i);
    }
    for(int i=1;i<=cnt;i++)
        for(int j=i;j<=cnt;j++)//不是从i+1,因为0和0可以相邻 
            if((s[i]&s[j])==0&&(s[i]&(s[j]>>1))==0&&(s[i]&(s[j]<<1))==0)
                sid[i][j]=1,sid[j][i]=1;
}
int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=cnt;i++)f[1][i][num[i]]=1;
    for(int i=2;i<=n;i++)
        for(int j=1;j<=cnt;j++)
            for(int k=1;k<=cnt;k++) if(sid[j][k])
                for(int l=num[k];l<=m;l++)
                {
                    f[i][k][l]+=f[i-1][j][l-num[k]];
//                    if(f[i-1][j][l-num[k]])printf("i=%d : %d->%d ,l=%d f=%d\n",i,s[j],s[k],l,f[i][k][l]);
                }        
    for(int i=1;i<=cnt;i++)
        ans+=f[n][i][m];
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-06-05 21:50  Zinn  阅读(116)  评论(0编辑  收藏  举报