C++之路进阶——状态压缩dp(互不侵犯)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++之路进阶——状态压缩dp(互不侵犯)相关的知识,希望对你有一定的参考价值。
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。
代码:
1 #include<cstdio> 2 #include<iostream> 3 #define maxn 600 4 #include<algorithm> 5 6 using namespace std; 7 8 int n,m,b1[maxn],b2[maxn][maxn],sum[maxn]; 9 long long f[10][maxn][maxn]; 10 11 int main() 12 { 13 scanf("%d%d",&n,&m); 14 int s=(1<<n)-1; 15 for (int i=0;i<=s;i++) 16 if ((i&(i>>1))==0) 17 { 18 b1[i]=1; 19 int q=0; 20 for (int j=i;j;j=j>>1) 21 if (j&1) 22 q++; 23 sum[i]=q; 24 } 25 for (int i=0;i<=s;i++) 26 if (b1[i]) 27 for (int j=0;j<=s;j++) 28 if (b1[j]&&(i&j)==0&&((i<<1)&j)==0&&((i>>1)&j)==0) 29 b2[i][j]=1; 30 for (int i=0;i<=s;i++) 31 f[1][sum[i]][i]=1; 32 for (int i=1;i<n;i++) 33 for (int j=0;j<=s;j++) 34 if (b1[j]) 35 for (int k=0;k<=s;k++) 36 if (b1[k]&&b2[j][k]) 37 { 38 for (int q=sum[j];q+sum[k]<=m;q++) 39 f[i+1][sum[k]+q][k]+=f[i][q][j]; 40 } 41 long long ans=0; 42 for (int i=0;i<=s;i++) 43 ans+=f[n][m][i]; 44 printf("%lld\n",ans); 45 return 0; 46 }
以上是关于C++之路进阶——状态压缩dp(互不侵犯)的主要内容,如果未能解决你的问题,请参考以下文章
状态压缩dpbzoj1087: [SCOI2005]互不侵犯King
[Bzoj1087][SCOI2005]互不侵犯King(状压dp)