POJ 1036 Gangsters DP 多解
来源:互联网 发布:java spring框架 入门 编辑:程序博客网 时间:2024/06/04 18:29
题意:一群匪徒要进入一个酒店。酒店的门有k+1个状态,每个匪徒的参数是:进入时间,符合的状态,携带的钱。
酒店的门刚开始状态0,问最多这个酒店能得到的钱数。
思路1:dp[i][j]表示时间0-i之间,门的状态为j时所能获得的最大利益
转移方程 :dp[i][j]=max(dp[i-1][j],dp[i-1][j-1],dp[i-1][j+1])
因为转移i只跟i-1有关,所以可以用滚动数组dp[2][k]
有一个处理边界的好方法:
j的范围 0 —k,不妨向右移动1位,并保证0,k+2时的状态为0
代码1:
View Code
//O(k*t)#include<stdio.h>#include<string.h>int max(int a, int b) { return a > b ? a : b;}int tt[103], s[103], p[103], dp[2][103], a[30004][103];int main(){ int i, j; int n, k, t; while( ~scanf("%d%d%d", &n, &k, &t)) { for(i = 1; i <= n; i++) scanf("%d", &tt[i]); for(i = 1; i <= n; i++) scanf("%d", &p[i]); for(i = 1; i <= n; i++) scanf("%d", &s[i]); memset(dp, 0, sizeof(dp)); memset(a, 0, sizeof(a)); for(i = 1; i <= n; i++) if(tt[i] >= s[i]) //把一定不能进入的删去,它会影响状态转移 //保证0,k+2时的状态为0 a[tt[i]][s[i]+1] += p[i]; for(i = 1; i <= t; i++) for(j = 1; j <= k+1 && j <= i+1; j++) dp[i&1][j] = max( dp[(i-1)&1][j+1], max(dp[(i-1)&1][j-1], dp[(i-1)&1][j]) ) + a[i][j]; int ans = 0; for(i = 1; i <= k+1; i++) ans = max(ans, dp[t&1][i]); printf("%d\n", ans); } return 0;}
代码2:
View Code
//O(k*n)#include<stdio.h>#include<string.h>int max(int a, int b) { return a > b ? a : b;}int tt[103], s[103], p[103], dp[30003][103];int main(){ int i, j; int n, k, t; while( ~scanf("%d%d%d", &n, &k, &t)) { for(i = 1; i <= n; i++) scanf("%d", &tt[i]); for(i = 1; i <= n; i++) scanf("%d", &p[i]); for(i = 1; i <= n; i++) scanf("%d", &s[i]); memset(dp, 0, sizeof(dp)); for(i = 1; i <= n; i++) if(tt[i] >= s[i]) //同代码1 dp[tt[i]][s[i]+1] += p[i]; for(i = 1; i <= t; i++) for(j = 1; j <= k+1 && j <= i+1; j++) dp[i][j] += max( dp[(i-1)][j+1], max(dp[(i-1)][j-1], dp[(i-1)][j]) ); int ans = 0; for(i = 1; i <= k+1; i++) ans = max(ans, dp[t][i]); printf("%d\n", ans); } return 0;}
思路2:
仔细一想思路1发现dp数组中时间(t)那一维的空间有很多不必要的操作,因此我们可以将数组的这一维优化到人数(n)。
先将n个人按时间从小到大排序。
dp[i][j]表示进行到第i个人,门的状态为j时所获得的最大利益
其实这里的思想是单调队列优化,这样1->2->3->....->n递推下去,。
View Code
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{ int t, p, s;}g[103];int max(int a, int b) { return a > b ? a : b;}int abs(int a) { return a > 0 ? a : -a; }bool cmp(node a, node b){ return a.t < b.t;}int dp[103][103];int main(){ int i, j; int n, k, t; while( ~scanf("%d%d%d", &n, &k, &t)) { for(i = 1; i <= n; i++) scanf("%d", &g[i].t); for(i = 1; i <= n; i++) scanf("%d", &g[i].p); for(i = 1; i <= n; i++) scanf("%d", &g[i].s); sort(g+1, g+n+1, cmp); memset(dp, -1, sizeof(dp)); g[0].s = g[0].t = 0; dp[0][0] = 0; for(i = 0; i < n; i++) { for(j = 0; j <= k; j++) { if(dp[i][j] == -1) continue; for(int u = 0; u <= k; u++) if(abs(j-u) <= g[i+1].t - g[i].t) dp[i+1][u] = max(dp[i+1][u], dp[i][j]); } if(dp[i+1][g[i+1].s] != -1) dp[i+1][g[i+1].s] += g[i+1].p; } int ans = -1; for(i = 0; i <= k; i++) ans = max(ans, dp[n][i]); printf("%d\n", ans); } return 0;}
以上的情况,还可以再优化
用dp[i]表示表示进行到第i个人所获得的最大利益
递推做了改变, i的状态可以是从 0---(i-1)这些状态推过来
View Code
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int ABS(int a) { return a > 0 ? a : -a; }int max(int a, int b) { return a > b ? a : b; }struct node{ int t,p,s;}g[101];bool cmp(node a, node b){ return a.t<b.t;}int dp[105];int main(){ int i,j,k,p,q,m,n,t; while(scanf("%d%d%d", &n, &k, &t)!=-1) { memset(dp, 0, sizeof(dp)); for(i = 0; i < n; i++) scanf("%d", &g[i].t); for(i = 0; i < n; i++) scanf("%d", &g[i].p); for(i = 0; i < n; i++) scanf("%d", &g[i].s); sort(g, g+n, cmp); for(i=0;i<n;i++) { dp[i] = (g[i].t>=g[i].s)? g[i].p : 0; for(j = 0; j < i; j++) { if(!dp[j]) continue; if(ABS(g[i].s-g[j].s) > g[i].t-g[j].t) continue; dp[i] = max(dp[i], dp[j]+g[i].p); } } int ans = 0; for(i = 0; i < n; i++) ans = max(ans, dp[i]); printf("%d\n",ans); } return 0;}
- POJ 1036 Gangsters DP 多解
- POJ 1036 Gangsters (DP)
- POJ 1036 Gangsters DP好题 多解
- poj 1036 Gangsters(DP)
- poj 1036 Gangsters (简单dp)
- POJ 1036 Gangsters 水dp。。
- POJ 1036 Gangsters(DP)
- poj 1036 Gangsters 简单dp
- POJ 1036 Gangsters(DP)
- poj - 1036 - Gangsters(滚动数组dp)
- poj 1036 Gangsters (DP:滚动数组)
- POJ 1036 Gangsters -- 常规dp 题意好难懂啊
- poj 1036 Gangsters
- poj 1036 Gangsters
- poj 1036 Gangsters
- POJ 1036 Gangsters
- POJ 1036 Gangsters
- POJ 1036 Gangsters
- ZOJ 2588 Burning Bridges 求割边
- hbase的thrift服务
- POJ 2942 Knights of the Round Table 边双连通分量求解
- codeforces 159D dp + strings 好题
- POJ 1014 Dividing 多重背包
- POJ 1036 Gangsters DP 多解
- 【转】POJ DP 分类
- MULE ESB参考网站所在位置
- POJ 1080 Human Gene Functions DP
- POJ 1141 Brackets Sequence 经典区间DP题
- POJ 1157 LITTLE SHOP OF FLOWERS 水DP
- POJ 2479 Maximum sum DP
- POJ 1952 BUY LOW, BUY LOWER DP 最长下降序列求个数
- POJ KMP 入门4题