JZOJ 1213. 棋盘上的士兵

题目

Description

       话说Jby发明了一个取石子游戏之后,一下就被聪明的你破解了….
       这次他又搞了一个新的游戏来折磨游戏者;
        Jby会给定的一个N*N的棋盘,而且要求你在棋盘中放M个士兵,使得士兵不能互相攻击,你的任务是求出有多少种不同的方案。对于每个士兵,他的攻击范围是他的对角线。如图所示: 
 

Input

仅有一行,两个数N和M。分别表示棋盘的大小和要放士兵的个数。

Output

仅有一行,表示方案数。
 

Sample Input

3 4

Sample Output

8
 

Data Constraint

对于60%的数据,N<=8,1<=m<=2*N-2
对于100%的数据,N<=15,1<=m<=2*N-2,且答案在Int64范围以内!!

 

分析

  • 正解还真的是状压但是我不知道数组怎么开于是只有60?

 

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 using namespace std;
 6 int n,m;
 7 long long map[32][32];
 8 long long f[2][1<<20];
 9 long long a[32]; 
10 void dfs(int x,int y)
11 {
12     if (x>(n+n)/2) return;
13     map[x][y]=0;
14     dfs(x+1,y-1),dfs(x+1,y+1);
15 }
16 int main ()
17 {
18     freopen("chess.in","r",stdin);
19     freopen("chess.out","w",stdout);
20     cin>>n>>m;
21     for (int i=1;i<=n+n-1;i++) for (int j=1;j<=n+n-1;j++) map[i][j]=1;
22     dfs(1,(n+n)/2);
23     for (int i=(n+n)/2+1,k=2;i<=n+n-1;i++,k+=2) for (int j=1;j<=n+n-1;j++) map[i][j]=map[i-k][j];
24     for (int i=1;i<=n+n-1;i++) for (int j=1;j<=n+n-1;j++) a[i]=(a[i]<<1)+map[i][j];
25     int maxn=(1<<(n+n-1))-1;
26     f[0][(1<<(n+n)/2-1)]=1;
27     f[0][0]=1;
28     int nn=n+n-1,x=0;
29     for (int i=2;i<=nn;i++)
30     {
31         x^=1;
32         for (int j=0;j<=maxn;j++)
33         {
34                 f[x][j]+=f[x^1][j];
35                 for (int k=1;k<=nn;k++)
36                 {
37                     if (!(j&(1<<k-1))&&!(a[i]&(1<<k-1)))
38                     f[x][j|(1<<k-1)]+=f[x^1][j];
39                 }
40         }
41         memset(f[x^1],0,sizeof(f[x^1]));
42     }
43     long long ans=0;
44         for (int j=0;j<=maxn;j++)
45             if (__builtin_popcount(j)==m) ans+=f[x][j];
46     cout<<ans;
47 }

 

 

posted @ 2019-07-15 10:36  Melted_czj  阅读(226)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色