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; }
相关文章推荐
- C++之路进阶——ST表(降雨量)
- C++之路进阶——四边不等式优化dp(诗人小G)
- word2vec中文相似词计算和聚类的使用说明及c语言源码
- c语言中的正则
- 【C++学习与应用总结】12: Unscoped Enum
- C语言杂谈:指针与数组 (上)
- c++STl的全排列
- C++之 浅拷贝和深拷贝
- neuq oj 1043: 谭浩强C语言(第三版)习题5.7 C语言
- 关于C语言include尖括号和双引号的对话
- C语言:【动态顺序表】动态顺序表的在指定位置插入元素Insert,以及指定元素Find
- 单件模式
- 74. Search a 2D Matrix
- 【hdu 2896】病毒侵袭 题解&代码(C++)
- C++之 构造函数调用规则
- 【源代码】将一个整数的每位数分解并按逆序放入一个数组中(用递归算法)(C语言实现)
- Basic C++ Container classes summary(Array, Vector, List)
- c语言入门之项目2.0——成绩等级
- C语言:【动态顺序表】动态顺序表的初始化、打印、尾插PushBack、尾删PopBack
- C++基础篇之 复制构造函数调用时机