【状态dp】poj 1185 炮兵阵地(三维dp)
2015-10-04 19:17
393 查看
poj 1185 炮兵阵地
加粗
斜体
引用
插入链接
插入代码
插入图片
提升标题
有序列表
无序列表
横线
撤销
重做
http://poj.org/problem?id=1185
问题描述:给你一个n行m列的P-H矩阵,H表示不能安置炮兵,1可以安置炮兵,要求炮兵攻击管辖内不能在安置其他炮兵,问最多可安置炮兵的数目思路: 状态压缩+位运算+动态规划
基本思路参考上一题http://blog.csdn.net/u012717411/article/details/48896791
1.注意与上一题有区别,这道题目问的是做多安置炮兵的数量,而不是排兵布阵的总方案数,所以状态转移方程要变了!!!
2.三维DP(因为每行的状态数不仅取决于上一行,还与再上一行有关系,需再引入一个变量,初始化也很麻烦~):dp[i][j][k]表示第i行状态为j第i-1行状态为k的情况,它取决于状态j与上一行状态k以及再上一行的可行状态是否两两冲突.枚举第i-2行所有状态p,若上一行状态p可行,dp[i][j][k] =max(dp[i][j][k],dp[i-1][k][p]+cnt[j]),cnt[j]表示状态为j的情况含有炮兵的个数(即二进制串1的个数),需要预处理。
状态转移方程不是很好想,可能这就是dp的难点~参考代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<vector> #include<set> #include<map> #include<algorithm> #include<sstream> #define eps 1e-9 #define pi acos(-1) #define long long ll #define M 10 #define N 110 using namespace std; const int _max = 60 + 10;//最多可能状况不超60种,太大或MLE const int mod = 1e8; int n,m,row ,top,st[_max]; int dp [_max][_max],cnt[_max]; char ch; bool judge(int x,int j){//自身地形合适 int y = st[j]; if(y&~x) return false; return true; } void init(){//状态压缩 top=0; for(int i = 0; i < (1<<m); ++ i){ if(i&(i<<1)) continue; if(i&(i<<2)) continue; st[++top] = i; int t = i,res = 0;; while(t){ if(t&1) res++; t>>=1; } cnt[top] = res; } } int main() { #ifndef ONLINE_JUDGE freopen("input.txt","r",stdin); #endif // ONLINE_JUDGE while(~scanf("%d%d",&n,&m)){ getchar(); for(int i = 1; i <= n; ++ i){ row[i] = 0; for(int j = 1; j <= m; ++ j){ scanf("%c",&ch); int x = ch=='P'?1:0; row[i]=(row[i]<<1)+x; } getchar(); } init(); memset(dp,0,sizeof(dp)); for(int i = 1; i <= top;++ i) if(judge(row[1],i)) dp[1][i][1] = cnt[i]; //dp for(int i = 2; i <= n; ++ i) for(int j = 1; j <= top; ++ j){ if(!judge(row[i],j)) continue;//自己行地形合适 for(int k =1; k<= top; ++ k){//i-1行状态 if(st[j]&st[k]) continue; for(int p = 1;p <= top; ++ p){//i - 2行状态 if(st[p]&st[j]) continue; if(st[p]&st[k]) continue; dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][i==2?1:p]+cnt[j]); } } } int tar = -1; for(int i = 1; i <= top; ++ i) for(int j = 1; j<= top; ++ j) if(tar < dp [i][j]) tar = dp [i][j]; printf("%d\n",tar); } return 0; }
加粗
Ctrl + B
斜体
Ctrl + I
引用
Ctrl + Q
插入链接
Ctrl + L
插入代码
Ctrl + K
插入图片
Ctrl + G
提升标题
Ctrl + H
有序列表
Ctrl + O
无序列表
Ctrl + U
横线
Ctrl + R
撤销
Ctrl + Z
重做
Ctrl + Y
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)
- Word Break I,II, Triangle,Palindrome Partitioning 动态规划 DP