您的位置:首页 > 其它

bzoj1087 [SCOI2005]互不侵犯

2017-03-07 17:20 169 查看

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入门题,没什么好讲的吧。。

//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define ky (1<<n)
#define il inline
#define RG register
#define int long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)

using namespace std;

int f[10][85][1<<10],cnt[1<<10],n,k,ans;

il int gi(){
RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il int calc(RG int x){ RG int ans=0; while (x){ ans+=x&1,x>>=1; } return ans; }

il void work(){
n=gi(),k=gi();
for (RG int i=0;i<ky;++i){
cnt[i]=calc(i);
if ((i&(i>>1)) || (i&(i<<1))) continue;
f[1][cnt[i]][i]=1;
}
for (RG int i=2;i<=n;++i)
for (RG int s=0;s<ky;++s){
if (s&(s>>1) || (s&(s<<1))) continue;
for (RG int ss=0;ss<ky;++ss){
if (ss&(ss>>1) || (ss&(ss<<1)) || (s&ss) || (s&(ss>>1)) || (s&(ss<<1))) continue;
for (RG int p=cnt[ss];p+cnt[s]<=k;++p) f[i][p+cnt[s]][s]+=f[i-1][p][ss];
}
}
for (RG int i=0;i<ky;++i) ans+=f
[k][i]; printf("%lld\n",ans);  return;
}

main(){
File("king");
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: