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 }

 

posted @ 2017-03-07 17:20  wfj_2048  阅读(152)  评论(0编辑  收藏  举报