bzoj1087

状压DP

先判断可行的放法,在递推

#include<cstdio>
using namespace std;
int maxx,cnt[1025],n,m;
bool pd1[1025],pd2[1025][1025];
long long f[10][82][1025];
void work(){
    for(int i=0;i<=maxx;i++)
       if((i&(i>>1))==0){
           int tot=0;for(int x=i;x;x>>=1)tot+=(x&1);cnt[i]=tot;pd1[i]=1;
       }
    pd2[0][0]=1;
    for(int i=0;i<maxx;i++)if(pd1[i])
       for(int j=i+1;j<=maxx;j++)if(pd1[j])
          if(((i&(j>>1))==0)&&((j&(i>>1))==0)&&((i&j)==0))pd2[i][j]=pd2[j][i]=1;
}

int main(){
    scanf("%d%d",&n,&m);
    maxx=(1<<n)-1;
    work();
    for(int i=0;i<=maxx;i++)if(pd1[i])f[1][cnt[i]][i]=1;
    for(int i=1;i<n;i++)
      for(int k=0;k<=maxx;k++)if(pd1[k])
         for(int j=0;j<=maxx;j++)if(pd1[j])
            if(pd2[k][j])
               for(int p=cnt[k];p+cnt[j]<=m;p++)
                 f[i+1][p+cnt[j]][j]+=f[i][p][k];
    long long ans=0;
    for(int i=0;i<=maxx;i++)ans=ans+f[n][m][i];
    printf("%lld",ans);
}

 

posted @ 2018-05-02 16:03  lnyzo  阅读(122)  评论(0编辑  收藏  举报