码迷,mamicode.com
首页 > 其他好文 > 详细

sgu233 little kings

时间:2015-06-30 12:36:55      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:

题目大意: 有n*n的棋盘上放k个国王。国王可以攻击与它相邻的八个格子。现在要使国王不相互攻击,有多少种放置的方案数。一个格子不能放两个国王。

n<=10,k<=n*n。

分析:简单的状态压缩DP。f[i][state][j]表示第i行放置国王的状态为state,前i行一共放了j个国王的方案数,state为位压缩表示的状态,某位为1,表示该处放了国王,为0表示没有放。合法的state状态数是有限的,所以,可以预处理出一行当中所有合法的state状态,保存在数组中。

f[i][p1][j]=∑(f[i-1][p2][j-cnts[state]]) {(state[p2]&state[p1])==0&&((state[p2]>>1)&state[p1]==0)&&((state[p2]<<1)&state[p1]==0)}

最后的答案即为∑f[n][j][k] {枚举j}

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int n,k,num=0,s[1200],c[1200];
 6 long long f[2][1100][120];
 7 void dfs(int i,int state,int cnt)
 8 {
 9     if(i>=n)
10     {s[++num]=state;
11      c[num]=cnt;
12         return;
13     }
14     dfs(i+1,state<<1,cnt);
15     if(state&1)return;
16     dfs(i+1,(state<<1)+1,cnt+1);
17 }
18 int main()
19 {
20     while(scanf("%d%d",&n,&k)!=-1)
21     {
22     memset(f,0,sizeof f);
23     num=0;
24     dfs(0,0,0);
25     for(int i=1;i<=n;i++)
26     {
27         for(int j=1;j<=num;j++)
28         {if(i==1)f[i&1][j][c[j]]=1;
29             else
30             for(int p=c[j];p<=k;p++)
31             {
32                 f[i&1][j][p]=0;
33                 for(int x=1;x<=num;x++)
34                 {
35                     if(c[x]+c[j]<=p&&(s[x]&s[j])==0&&((s[x]&(s[j]<<1))==0)&&((s[x]&(s[j]>>1))==0))
36                         f[i&1][j][p]+=f[!(i&1)][x][p-c[j]];
37                 }
38             }
39         }
40     }
41     long long ans=0;
42     for(int j=1;j<=num;j++)
43         ans+=f[n&1][j][k];
44     printf("%I64d\n",ans);
45 }
46 }

 

sgu233 little kings

标签:

原文地址:http://www.cnblogs.com/hefenghhhh/p/4609822.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!