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

【题目分析】

    沉迷水题,吃枣药丸。

    

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define ll long long
int cot[512],c1[512],c2[512][512],n,p;
ll dp[10][512][90];
void print(int x)
{
    F(i,0,n-1) printf("%d",(x>>i)&1);
}
void init()
{
    F(i,0,(1<<n)-1)
    {
        int x=i,ret=0;
        while (x) ret+=x&1,x>>=1;
        cot[i]=ret;
    }
    F(i,0,(1<<n)-1)
        if ((!((i>>1)&i))&&(!((i<<1)&i))) c1[i]=1;
    F(i,0,(1<<n)-1) if (c1[i])
    F(j,0,(1<<n)-1) if (c1[j])
    if ((!((j>>1)&i))&&(!((j<<1)&i))&&(!(j&i)))
        {
//          print(i); printf("---> "); print(j); printf("\n");
            c2[i][j]=1;
        }
}
int main()
{
    scanf("%d%d",&n,&p);
    init();
    F(i,0,(1<<n)-1) if (c1[i]) dp[1][i][cot[i]]=1;
    F(i,1,n-1) F(j,0,(1<<n)-1)
    F(k,0,p)   F(l,0,(1<<n)-1)
        if (c2[j][l])
        {
//          printf("dp[%d] ",i+1); print(l); printf(" %d += dp[%d] ",k+cot[l],i); print(j); printf(" %d  = %d\n",k,dp[i][j][k]);
            dp[i+1][l][k+cot[l]]+=dp[i][j][k];
        }
    ll ans=0;
    F(i,0,(1<<n)-1) ans+=dp[n][i][p];
    printf("%lld\n",ans);
}

  

posted @ 2017-02-23 21:08  SfailSth  阅读(158)  评论(0编辑  收藏  举报