/* 好神奇好神奇...表示自己要学的还很多 注意到n<=9 不是搜索就是状丫 搜索+剪枝 70分 枚举放或者不放 这里用状丫 f[i][j][k] 表示前i行 放了j个国王 i行的状态是k的方案数 转移的话 枚举下层的状态 算出这个状态中有几个国王 然后更新 复杂度 2^n*2^n*n*K*n 最后一个n是算国王数 这个可以预处理搞出来 还有一个问题就是 互相伤害的问题 首先在同一行里 相邻的不行 不同行的就左移右移一下就好了 顺带处理好两个状态能不能互相转移 最后Σf[n][K][i] */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 520 using namespace std; int n,K,v1[maxn],v2[maxn][maxn],cnt[maxn]; long long ans,f[10][100][maxn]; void Get_v() { for(int i=0;i<(1<<n);i++) if((i&(i>>1))==0) { v1[i]=1;int c=0; for(int j=i;j;j>>=1)c+=j&1; cnt[i]=c; } for(int i=0;i<(1<<n);i++)if(v1[i]) for(int j=0;j<(1<<n);j++)if(v1[j]) if((i&j)==0&&(i&(j>>1))==0&&(j&(i>>1))==0) v2[i][j]=1; } int main() { cin>>n>>K; Get_v(); for(int i=0;i<(1<<n);i++) f[1][cnt[i]][i]=1; for(int i=2;i<=n;i++) for(int j=0;j<(1<<n);j++)if(v1[j]) for(int k=0;k<(1<<n);k++)if(v2[j][k]) for(int r=cnt[j];r+cnt[k]<=K;r++) f[i][r+cnt[k]][k]+=f[i-1][r][j]; for(int i=0;i<(1<<n);i++) ans+=f[n][K][i]; cout<<ans<<endl; return 0; }
时间: 2024-12-29 10:06:04