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); }