bzoj[1087][SCOI2005]互不侵犯King
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
题解
#include<stdio.h> int n,m; bool st[600],ts[600][600]; long long sum[600],f[2][121][600]; int main(){ scanf("%d%d",&n,&m); for(int i=0;i<(1<<n);i++) if(!((i>>1)&i)){ for(int x=i;x;x>>=1) sum[i]+=x&1; st[i]=1; } for(int i=0;i<(1<<n);i++){ if(!st[i]) continue; for(int j=0;j<=i;j++) if(st[j]&&(!(i&j))&&(!(i&(j>>1)))&&(!((i>>1)&j))) ts[i][j]=ts[j][i]=1; } int c=0; for(int i=0;i<(1<<n);i++) f[c][sum[i]][i]=1; for(int t=1;t<n;t++){ c^=1; for(int i=0;i<(1<<n);i++) for(int j=0;j<=m;j++) f[c][j][i]=0; for(int i=0;i<(1<<n);i++){ if(!st[i]) continue; for(int j=0;j<(1<<n);j++) if(st[j]&&ts[i][j]) for(int p=sum[j];p<=m-sum[i];p++) f[c][p+sum[i]][i]+=f[c^1][p][j]; } } long long ans=0; for(int i=0;i<(1<<n);i++) ans+=f[c][m][i]; printf("%lld\n",ans); return 0; }