poj1185 炮兵阵地(状态压缩dp)
来源:互联网 发布:合肥软件开发 编辑:程序博客网 时间:2024/06/05 07:18
这题。。。换成3维后,果断更不好做了啊
首先说说为什么换成三维,dp数组有个特点,由前一个状态才能得到下一个状态,这样做的前提就是必须要保存前面状态的下标,而这个要兼顾前两行状态,所以由二维变为三维。变为三维后,就有个建模的过程。三维建模有两种,假设高为h,一种是直接立方体,另一种是h个矩形,这个题还是用立方体想比较好。
然后是数组的大小,这里有人说top为60,这个60怎么来的呢?二进制数一共10位,总共2^10 - 1,但其实一行最多放4个炮,所以就开始分类:
0个炮:1种;
1个炮:10种;
2个炮:?
3个炮:?
4个炮:1种。
重点是2和3个炮,(例如2个)这相当于先求当4对炮相邻有多少种方法,然后在乘C(2上, 5下)(不会插数学符号T T。。。)。3个炮也是类似,然而我现在不会求了,数学渣T T,所以只能留白了,以后复习了概率论再算吧。。。
再次是求动态方程。上一题玉米是求方案数,这一题是求最多放炮数,所以最后不需要累加,只是求最值就好(其实最大值也往往在数组下面)。
动态方程:dp[i][k][t] = max(dp[i][k][t], dp[i - 1][j][k] + num[t])。
注意t代表当前行,k代表上一行,j代表上上行,这样就好理解了。每次判断前的剪枝不要忘掉。
对了还有个位运算x &= (x - 1);统计1的个数,也比较经典,记住就好了。
说白了,这两道状压要在理解加记忆的基础上才能A掉,特别是这种长代码,哎,只能多做题加深印象了,总不能死记吧。。。
#include <stdio.h>#include <algorithm>#include <string.h>#include <iostream>using namespace std;const int N = 60;const int INF = 1e8;const int mod = 100000000;int n, m, top, total;int state[N], cur[105], dp[105][N][N], num[N];bool ok(int x){ if(x & (x << 1)) return false; if(x & (x << 2)) return false; else return true;}void init(){ top = 0; total = 1 << m; for(int i = 0; i < total; i ++) { if(ok(i)) state[++ top] = i; }}bool fit(int x, int y){ if(x & y) return false; else return true;}int jcount(int x){ int cnt = 0; while(x) { cnt ++; x &= (x - 1); } return cnt;}int main(){ // freopen("in.txt", "r", stdin); char c; while(~scanf("%d%d", &n, &m)) { memset(dp, -1, sizeof(dp)); init(); //输入,同时记录该行的状态 for(int i = 1; i <= n; i ++) { cur[i] = 0; for(int j = 1; j <= m; j ++) { cin >> c; if(c == 'H') cur[i] += (1 << (m - j)); } } //初始化第一行 for(int i = 1; i <= top; i ++) { num[i] = jcount(state[i]); if(fit(state[i], cur[1])) dp[1][1][i] = num[i]; } //分层dp for(int i = 2; i <= n; i ++) { for(int t = 1; t <= top; t ++)//当前行 { if(!fit(state[t], cur[i])) continue; for(int j = 1; j <= top; j ++)//上上行 { if(!fit(state[j], cur[i - 2])) continue; if(state[t] & state[j]) continue; for(int k = 1; k <= top; k ++) //上一行 { if(!fit(state[k], cur[i - 1])) continue; if(state[t] & state[k]) continue; if(dp[i - 1][j][k] == -1) continue; dp[i][k][t] = max(dp[i][k][t], dp[i - 1][j][k] + num[t]); } } } } //输出 int ans = 0; for(int i = 1; i <= n; i ++) for(int j = 1; j <= top; j ++) for(int k = 1; k <= top; k ++) ans = max(ans, dp[i][j][k]); printf("%d\n", ans); } return 0;}
0 0
- poj1185 炮兵阵地 (DP状态压缩)
- POJ1185 炮兵阵地 (状态压缩DP)
- poj1185 炮兵阵地(状态压缩dp)
- poj1185 炮兵阵地(状态压缩dp)
- poj1185炮兵阵地(状态压缩dp)
- POJ1185 炮兵阵地 (状态压缩DP)
- POJ1185炮兵阵地(状态压缩DP)
- 状态压缩DP poj1185 炮兵阵地
- poj1185 炮兵阵地 状态压缩dp
- poj1185 炮兵阵地 状态压缩dp
- poj1185 炮兵阵地(状态压缩+DP)
- poj1185炮兵阵地(状态压缩DP)
- POJ1185 炮兵阵地 状态压缩DP
- POJ1185——炮兵阵地(状态压缩DP)
- POJ1185——炮兵阵地(状态压缩dp)
- poj1185 炮兵阵地(状态压缩)
- POJ1185 炮兵阵地(压缩DP)
- POJ1185:炮兵阵地(状态压缩)
- Android高仿path小球刷新效果,类似iOS果冻效果
- Clang和LLVM学习(Day2)
- Android中的IPC方式
- 接口测试
- Android 反编译apk
- poj1185 炮兵阵地(状态压缩dp)
- LRU缓存实现(Java)
- MAC OS下maven环境变量配置
- C 语言 实现大数相乘问题(包括正、负整数,另外还附有详细注释)
- php连接sqlserver的方法
- Maven父子项目打包子项目出现Failed to collect dependencies问题
- [C++]vector 的 push_back实现原理
- 【数据存储】——JSON与XML的对比
- 模板:Edmonds_Karp 算法