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
 
状压DP。。。
f[i][j][k]表示前j-1行选了i个人,第j行状态为k时的方案总数。。。
所以状态转移方程就是f[i+sum][j][k]+=f[i][j-1][l] sum是状态k中放的棋子数。。
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 10000+5
14 #define maxm 10000+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int read(){
24     int x=0,f=1;char ch=getchar();
25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 ll f[100][10][600];
30 int n,m,a[maxn];
31 int main(){
32     //freopen("input.txt","r",stdin);
33     //freopen("output.txt","w",stdout);
34     memset(f,0,sizeof(f));
35     n=read();m=read();a[1]=1;
36     for(int i=2;i<=10;i++)
37         a[i]=a[i-1]<<1;
38     f[0][0][0]=1;
39     for1(j,n)
40         for0(i,m)
41             for0(k,a[n+1]-1){
42                 if((k>>1&k)||(k<<1&k))continue;
43                 int tmp=k,tot=0;
44                 while(tmp){
45                     tot+=tmp&1;tmp>>=1;
46                 }
47                 if(tot>i)continue;
48                 for0(l,a[n+1]-1){ 
49                     if((l>>1&l)||(l<<1&l))continue;
50                     if((l&k)||(l<<1&k)||(l>>1&k))continue;
51                     int tmp2=l,tot2=0;
52                     while(tmp2){
53                         tot2+=tmp2&1;tmp2>>=1;
54                     }
55                     if(tot2>m-i)continue;
56                     f[i+tot2][j][l]+=f[i][j-1][k];
57                 } 
58             }
59     ll ans=0;
60     for0(i,a[n+1]-1)
61         ans+=f[m][n][i];
62     printf("%lld\n",ans);
63     return 0;
64 }
View Code

 

posted @ 2016-05-26 16:40  HTWX  阅读(116)  评论(0编辑  收藏  举报