1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4593 Solved: 2662
[Submit][Status][Discuss]
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
HINT
Source
这不是跟炮兵阵地一样一样的题嘛QAQ 把每一行可行的情况先预处理出来,再把行之间可行的情况预处理出来,最后DP求和即可qwq 注意!!! (i&(1<<1))==0 最外面的括号一定一定一定要打!!!!已经两题因为这个错找半天了 _(:зゝ∠)_
1 #include "bits/stdc++.h" 2 using namespace std; 3 typedef long long LL; 4 LL n,m,f[15][105][1<<11],num[512],ans; 5 bool b[512],a[512][512]; 6 void pre(){ 7 LL i,j,s; 8 for (i=0;i<(1<<n);i++) 9 if ((i&(i<<1))==0){ 10 s=0; 11 for (j=i;j;j>>=1) s+=j&1; 12 num[i]=s,b[i]=true; 13 } 14 for (i=0;i<(1<<n);i++) 15 if (b[i]) 16 for (j=0;j<(1<<n);j++) 17 if (b[j]) 18 if ((i&j)==0 && (i&(j<<1))==0 && ((i<<1)&j)==0) 19 a[i][j]=true; 20 } 21 int main(){ 22 freopen ("king.in","r",stdin);freopen ("king.out","w",stdout); 23 LL i,j,k,x; 24 scanf("%lld%lld",&n,&m); 25 pre(); 26 for (i=0;i<(1<<n);i++) if (b[i]) f[1][num[i]][i]=1; 27 for (i=1;i<n;i++) 28 for (j=0;j<(1<<n);j++) if (b[j]) 29 for (k=0;k<(1<<n);k++) if (b[k] && a[j][k]) 30 for (x=num[j];x+num[k]<=m;x++) 31 f[i+1][num[k]+x][k]+=f[i][x][j]; 32 for (i=0;i<(1<<n);i++) ans+=f[n][m][i]; 33 printf("%lld",ans); 34 return 0; 35 }