bzoj1087 [SCOI2005]互不侵犯
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
正解:状压dp。
状压dp入门题,没什么好讲的吧。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define ky (1<<n) 16 #define il inline 17 #define RG register 18 #define int long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int f[10][85][1<<10],cnt[1<<10],n,k,ans; 24 25 il int gi(){ 26 RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 27 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 28 } 29 30 il int calc(RG int x){ RG int ans=0; while (x){ ans+=x&1,x>>=1; } return ans; } 31 32 il void work(){ 33 n=gi(),k=gi(); 34 for (RG int i=0;i<ky;++i){ 35 cnt[i]=calc(i); 36 if ((i&(i>>1)) || (i&(i<<1))) continue; 37 f[1][cnt[i]][i]=1; 38 } 39 for (RG int i=2;i<=n;++i) 40 for (RG int s=0;s<ky;++s){ 41 if (s&(s>>1) || (s&(s<<1))) continue; 42 for (RG int ss=0;ss<ky;++ss){ 43 if (ss&(ss>>1) || (ss&(ss<<1)) || (s&ss) || (s&(ss>>1)) || (s&(ss<<1))) continue; 44 for (RG int p=cnt[ss];p+cnt[s]<=k;++p) f[i][p+cnt[s]][s]+=f[i-1][p][ss]; 45 } 46 } 47 for (RG int i=0;i<ky;++i) ans+=f[n][k][i]; printf("%lld\n",ans); return; 48 } 49 50 main(){ 51 File("king"); 52 work(); 53 return 0; 54 }