bzoj1087[SCOI2005]互不侵犯King

bzoj1087[SCOI2005]互不侵犯King

题意:

在N×N的棋盘里面放K个国王,使他们互不攻击,求共有多少种摆放方案。国王能攻击到它上下左右及左上左下右上右下八个方向上附近的一个格子,共8个格子。

题解:

状压dp。我的做法是像插头dp那样保存当前列右侧的上一行和当前列左侧的当前行的情况,同时加一列存左上角的状态,逐格递推,滚动掉行列的状态表示。过倒是过了然而是状态版上的倒数第一。我状压dp递推的时候不知道怎么省状态,可能写记忆化搜索会快一些,但就不能滚动了。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 using namespace std;
 6 
 7 long long x[100][10000],y[100][10000],n,k;
 8 inline bool bit(int x,int y){return x&(1<<(y-1));}
 9 inline int set(int x,int y,bool z){
10     if(z)return x|(1<<(y-1));else return x&((1<<(n+1))-1-(1<<(y-1)));
11 }
12 int main(){
13     scanf("%d%d",&n,&k); x[k][0]=1;
14     inc(i1,1,n)inc(j1,1,n){
15         inc(i2,0,k)inc(j2,0,(1<<(n+1))-1)y[i2][j2]=0;
16         inc(i2,0,k)inc(j2,0,(1<<(n+1))-1){
17             if(i2&&(j1==1||(! bit(j2,j1-1)))&&(i1==1||(! bit(j2,j1)))&&(i1==1||j1==1||(! bit(j2,n+1)))&&(j1==n||(! bit(j2,j1+1))))
18                 y[i2-1][set(set(j2,n+1,bit(j2,j1)),j1,1)]+=x[i2][j2];
19             y[i2][set(set(j2,n+1,bit(j2,j1)),j1,0)]+=x[i2][j2];
20         }swap(x,y);
21     }
22     long long ans=0; inc(i,0,(1<<(n+1))-1)ans+=x[0][i]; printf("%lld",ans);
23     return 0;
24 }

 

20160329

posted @ 2016-07-21 20:03  YuanZiming  阅读(275)  评论(0编辑  收藏  举报