两道需要排序的dp背包下问题 -- hdu 2546 饭卡/ hdu 3466 Proud Merchants
来源:互联网 发布:seo关键词优化软件 编辑:程序博客网 时间:2024/06/07 20:25
饭卡 (hdu 2546)
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 13144 Accepted Submission(s): 4550
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
1505101 2 3 2 1 1 2 3 2 1500
-4532
m元买n种东西,与背包问题很相似,但是多个约束条件 当余额>5元才可以继续买。
仅仅按照普通的背包思路问题来看的话, 假设状态"m元买n种商品所能剩下的最小余额"表示为f(n,m),那么先考虑第n种商品,最简单的情况就是第n种商品不买,那么f(n,m)=f(n-1,m)。
再看买第n种的情况,首先必须满足m>5, 假如买完后余额为负数p[n]>m显然就不用继续往下买了,此时f(n,m)=m-p[n].
而当p[n]<=m时,正常来说应该状态转移为 f(n, m) = f(n-1, m-p[n]), 但是这里有个问题就是每次买商品都要余额大于5,那么买商品之间的顺序就会影响,比如余额11,两种商品分别需要10,5.先买第一种就不能买第二种了,先买第二种的话还能买第一种。所以挑选第n个商品可能会有后效性。考虑如果想买k种商品,最好每次买完余额尽可能大于5,也就是假如这k种能同时买的话一定是先买最小的那种,先挑价格小的就不会影响后面挑价格大的。
基于这种考虑,我们可以先对商品按价格从大到小排序,因为我们是将前n种转移到前n-1种(也就是先挑第n种)。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 1005int p[maxn];int dp[maxn][maxn];int cmp(const int& a, const int&b){ return a>b;}int main(){ int n, m; while(~scanf("%d", &n)){ if(!n) break; for(int i = 1; i <= n; i++) scanf("%d", p+i); scanf("%d", &m); sort(p+1, p+n+1, cmp); //从大到小排序 for(int i = 0; i < maxn; i++) //初始状态 dp[0][i]=i; for(int i = 1; i<= n; i++) for(int j = 1; j <= m; j++){ dp[i][j] = dp[i-1][j]; //第i种不挑 if(j>=5 && j >= p[i]) dp[i][j] = min(dp[i][j], dp[i-1][j-p[i]]); //挑第i种且余额为正 else if(j >= 5) dp[i][j] = min(dp[i][j], j-p[i]); //挑完余额为负 } printf("%d\n", dp[n][m]); } return 0;}
当然这个问题还可以用一维滚动数组优化空间消耗,这里主要为了直观。
Proud Merchants(hdu 3466)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 2955 Accepted Submission(s): 1224
The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi.
If he had M units of money, what’s the maximum value iSea could get?
Each test case begin with two integers N, M (1 ≤ N ≤ 500, 1 ≤ M ≤ 5000), indicating the items’ number and the initial money.
Then N lines follow, each line contains three numbers Pi, Qi and Vi (1 ≤ Pi ≤ Qi ≤ 100, 1 ≤ Vi ≤ 1000), their meaning is in the description.
The input terminates by end of file marker.
2 1010 15 105 10 53 105 10 53 5 62 7 3
511
这道题目思路跟上一题思路基本一样。有m元n种商品,每种商品价值v[i],价格p[i],求能获得最大价值,约束条件是每种商品买之前余额必须大于q[i]. 同样的问题,买一种商品后改变了余额会影响其他商品的购买,也就是必须考虑购买的顺序。那么先买什么呢,答案是q[i]-p[i]最大的。
有个比较简单粗暴的证明,假设买a,b两种商品,对应Pa,Qa. Pb,Qb。假如要先买a商品,那么最少余额为Pa+Qb,假如先买b商品,那么最少余额为 Pb+Qa. 想要先买a的话必须满足, Pa+Qb<Pb+Qa ==> Qa-Pa>Qb-Pb
其实上一题先买小的同样也是这道题目的特殊情况,只不过他们对应的Q值都是为5而已,即5-Pa>5-Pb ==> Pa<Pb
#include <iostream>#include <algorithm>#include <cstring>using namespace std;#define maxn 505struct data{ int p; int q; int v; bool operator < ( const data & a) const { return q-p < a.q-a.p; }};data arr[maxn];int dp[5005]; //一维滚动数组节省空间int main(){ int n, m; while(cin >> n >> m){ memset(dp, 0, sizeof(dp)); dp[0] = 0; for(int i = 1; i <= n; i++) cin >> arr[i].p >> arr[i].q >> arr[i].v; sort(arr+1, arr+n); //按照q-p从小到大排序 for(int i = 1; i <= n; i++) for(int j = m; j>=1; j--) if(j >= arr[i].q && j >= arr[i].p) dp[j] = max(dp[j], dp[j-arr[i].p]+arr[i].v); cout << dp[m] << endl; } return 0;}
- 两道需要排序的dp背包下问题 -- hdu 2546 饭卡/ hdu 3466 Proud Merchants
- HDU Proud Merchants 【需要排序的0/1背包问题】
- HDU 3466 Proud Merchants 需要排序的背包
- hdu 3466 Proud Merchants (排序的dp)
- hdu 3466(排序+背包)Proud Merchants
- hdu 3466 Proud Merchants <背包+sort排序>
- HDU 3466 Proud Merchants (01背包排序问题)
- HDU 3466 Proud Merchants (背包问题)
- hdu 3466 Proud Merchants(背包问题)
- HDU-3466-Proud Merchants(01背包问题)
- hdu 3466 Proud Merchants(先排序的01背包)
- HDU 3466 Proud Merchants(排序的01背包)@
- 【背包】HDU 3466 Proud Merchants DP 分享排序方式的证明。。
- HDU 3466 Proud Merchants(某种顺序下的背包)
- HDU 3466 Proud Merchants DP 分享排序方式的证明。。
- HDU 3466 Proud Merchants(DP:01背包+贪心)
- hdu 3466 Proud Merchants(0-1背包+排序)
- HDU 3466 Proud Merchants(01背包+排序)
- 《算法导论》笔记:前言
- DIV布局如何正确的使用 id 和 class
- NSMutableArray--可变数组
- listView 动态设置高度
- 3D MMORPG游戏设计之技能系统
- 两道需要排序的dp背包下问题 -- hdu 2546 饭卡/ hdu 3466 Proud Merchants
- 视频发展趋势收集1--HBO起内讧 被迫外包流媒体服务
- C语言控制cpu使用率
- OC中的反射机制
- Hibernate @Transient
- NSDictionary--字典
- hibernate的<class name=" " table=" " schema=" "> 中schema的问题
- finalize应用
- EularProject 7: 计算10001个素数