hdu 3466 Proud Merchants 01背包 (顺序性)

来源:互联网 发布:摄影测量数据处理软件 编辑:程序博客网 时间:2024/04/30 19:34

Proud Merchants

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 3989    Accepted Submission(s): 1658


Problem Description
Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more.
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?

 

Input
There are several test cases in the input.

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.

 

Output
For each test case, output one integer, indicating maximum value iSea could get.

 

Sample Input
2 1010 15 105 10 53 105 10 53 5 62 7 3
 

Sample Output
511
 

Author
iSea @ WHU
 

Source
2010 ACM-ICPC Multi-University Training Contest(3)——Host by WHU
 

Recommend
zhouzeyong   |   We have carefully selected several similar problems for you:  3460 3463 3468 3467 3465 


与动态规划的顺序性息息相关,我认为这就是dp的难点之一。

解题报告(分为两次,第一次2015年写,第二次2016年3月16日):
题意:

在01背包基础上,每个物品仅有1个,花费cost,当有need钱时才能买,价值val,给定一定数目的钱,问最大价值。


2016回顾,再次思考:

其实我觉得要我严格证明这个题目为什么要采用qi-pi从小到大排序仍然很难,网上虽然给出了一些证明,但大多不是很清晰,有的推理还有漏洞,只是单方面的考虑部分情况,也不乏一些很细心而且正确的证明,可惜太长看不下去。

首先,题目肯定是要排序的,而且根据动态规划的顺序性(无后效性),排在最前面的物品,是一个购买过程中最

后面才会购买的。




背包问题有一个与之联系紧密的问题:

1.背包问题:给定一定体积,求出最大价值。

2.密切相关的问题: 给定一些物品,要求购买这些物品的最小价值。

我想说这两个目标的实际决策方案是一样的。这也很显然

下面解决给出n个物品,购买全部所需的最小钱数:

我们先从最简单的情形入手: 所有物品只需要消耗价钱pi,不需要其余购买的限制条件,

而且我还要加入一个限制:所有物品的购买顺序必须是从第n个,到第1个(为了符合DP的无后效性)。

那么显然costMin[n]=p1+p2+...+pn;

注意啦!注意啦!现在加入一个条件:

第n个物品购买的条件是要满足现持有钱数>=qn,令Mi=qi-pi;

那么costMin[n]=p1+p2+...+pn+  Mn;

注意啦!注意啦!

现在第n-1个物品又有限制了,购买条件是要满足现持有钱数>=qn-1

那么若只考虑前n-1个物品,

costMin[n-1]=p1+p2+...+pn-1+M[n-1]

考虑前n个物品

costMin[n]

=  max(p1+p2+...+pn+ M[n],p1+p2+...+pn-1+ M[n-1]   )      //根据前面的简单情形,仔细想想为什么?

=  p1+p2+...+pn+ max( M[n],      M[n-1]-pn  )  


现在所有物品都加入限制条件:

costMin[n]=  p1+p2+...+pn+max{M[i] - (p[i+1]+p[i+2]+...+p[n]   )}


 
好啦,

这个形式的解和一个问题等价:

SGU  259  单机调度问题  贪心

你可以去看看这个问题是如何求解的:

我可以简单叙述一下:

                   

题意:

n件货物,每件货物有一个加工时间Ti和运输时间Li,而我们只有一台机器,每次只能加工一个货物。但是有无限个运输的工人,输出最小的完


成工作的总时间(从开始加工到运输完成)

解法:贪心,要排序,是这样排序的按照 Li从小到大排序。


我们可以看一下这个问题costMin[n]的公式:


costMin[n]=T1+T2+...+Tn+max{ L[i]-(T[i+1]+T[i+2]+...+T[n])    };



发现了没?和本题是一样的。



pi就是Ti,Mi就是Li,所以本题为了达到对于给定n个物品,购买所需钱数最小的最佳方案


  


就是按照Mi=qi-pi 从小到大排序,然后从排到最后的物品买起。




 

2015:

如果熟悉01背包,以下的状态转移和大致的顺序是能这样写出的。
这个问题的关键是如何给背包排序,然后按一定顺序进行分阶段的动态规划。
举个例子:
 cost need1 59227
如果按照 先2 后 1的顺序动态规划,那么体积为11的背包只能装下一件物品。
如果先1后2,它可装两件。
排序方法是:
struct BAG{    int cost,need,val;    bool operator<(const BAG y)const    {        return need-cost<y.need-y.cost;    }} bag[maxn];

当初我认为:need2-cost2>=need1就行,
后来看题解,发现确实是 need2-cost2>=need1-cost1即可。
因为(need1-cost1,need1]范围内没有进行状态转移。

关键是按顺序,本次转移利用的状态要是先前计算好了的。

对于排序的考虑,只要考虑任意两个物品之间怎么排即可。


#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<cctype>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI (4.0*atan(1.0))#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   ind<<1,le,mid#define rson    ind<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mk    make_pair#define _f     first#define _s     secondusing namespace std;//const int INF=    ;typedef long long ll;//const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);const int INF =0x3f3f3f3f;const int maxn= 500+20    ;const int maxV= 5000+20    ;//const int maxm=    ;int n,V,dp[maxV];struct BAG{    int cost,need,val;    bool operator<(const BAG y)const    {        return need-cost<y.need-y.cost;    }} bag[maxn];int main(){    while(~scanf("%d%d",&n,&V))    {        for(int i=1;i<=n;i++)        {            scanf("%d%d%d",&bag[i].cost,&bag[i].need,&bag[i].val);        }        sort(bag+1,bag+1+n);        memset(dp,0,(V+1)*sizeof dp[0]);        for(int i=1;i<=n;i++)        {            BAG & now= bag[i];            int cost=now.cost;            int need=now.need;            int val =now.val;            for(int v=V;v>=need;v--)            {                 dp[v]=max(dp[v-cost]+val ,dp[v]  );            }        }        printf("%d\n",dp[V]);    }    return 0;}


 
n件货物,每件货物有一个加工时间Ti和运输时间Li,而我们只有一台机器,每次只能加工一个货物。输出最小的完成工作的总时间(从开始加工到运输完成)
0 0
原创粉丝点击