您的位置:首页 > 编程语言 > C语言/C++

C++之路进阶——状态压缩dp(互不侵犯)

2016-02-20 07:55 239 查看

2451 互不侵犯

2005年省队选拔赛四川

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

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

输入描述 Input Description

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

输出描述 Output Description

方案数。

样例输入 Sample Input

3 2

样例输出 Sample Output

16

数据范围及提示 Data Size & Hint

1 <=N <=9, 0 <= K <= N * N

题解:

用二进制表示状态,进行dp。

代码:

#include<cstdio>
#include<iostream>
#define maxn 600
#include<algorithm>

using namespace std;

int n,m,b1[maxn],b2[maxn][maxn],sum[maxn];
long long f[10][maxn][maxn];

int main()
{
scanf("%d%d",&n,&m);
int s=(1<<n)-1;
for (int i=0;i<=s;i++)
if ((i&(i>>1))==0)
{
b1[i]=1;
int q=0;
for (int j=i;j;j=j>>1)
if (j&1)
q++;
sum[i]=q;
}
for (int i=0;i<=s;i++)
if (b1[i])
for (int j=0;j<=s;j++)
if (b1[j]&&(i&j)==0&&((i<<1)&j)==0&&((i>>1)&j)==0)
b2[i][j]=1;
for (int i=0;i<=s;i++)
f[1][sum[i]][i]=1;
for (int i=1;i<n;i++)
for (int j=0;j<=s;j++)
if (b1[j])
for (int k=0;k<=s;k++)
if (b1[k]&&b2[j][k])
{
for (int q=sum[j];q+sum[k]<=m;q++)
f[i+1][sum[k]+q][k]+=f[i][q][j];
}
long long ans=0;
for (int i=0;i<=s;i++)
ans+=f
[m][i];
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: