P1896 [SCOI2005]互不侵犯King
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
输入输出样例
输入样例#1:
3 2
输出样例#1:
16
这是一个显然的问题
然而我并看不懂wxl和hzwer等神犇的高大上代码
贴代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int s[520]; 7 int num[520]; 8 int states; 9 long long f[15][110][520]; 10 int n,k; 11 long long ans; 12 13 int main(){ 14 scanf("%d%d",&n,&k); 15 for(int i=0;i<(1<<n);i++){ 16 if(i&(i<<1)) continue; 17 int temp=i; 18 while(temp){ 19 num[states]+=(temp&1); 20 temp=temp>>1; 21 } 22 s[states++]=i; 23 } 24 for(int i=0;i<states;i++)//第一行特处理 25 if(num[i]<=k) f[1][num[i]][i]++; 26 for(int i=2;i<=n;i++) 27 for(int j=0;j<=k;j++) 28 for(int t=0;t<states;t++){ 29 if(num[t]>j) continue; 30 for(int q=0;q<states;q++){ 31 if(num[q]>j-num[t]) continue; 32 if(s[t]&s[q]) continue; 33 if((s[t]<<1)&s[q]) continue; 34 if(s[t]&(s[q]<<1)) continue; 35 f[i][j][t]+=f[i-1][j-num[t]][q]; 36 } 37 } 38 for(int i=0;i<states;i++) ans+=f[n][k][i]; 39 printf("%lld",ans); 40 return 0; 41 }