3466Proud Merchants(需消除后效性的01背包)

来源:互联网 发布:防伪查询系统源码 编辑:程序博客网 时间:2024/06/11 13:30


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
 

题意:你有点钱,想买东西,每个东西有价值和钱数,但是还有个条件,你拥有的金钱数必须大于等于这个物品规定的一个金钱数才能买。也就是说,这个物品有两个属性,一个是价格,一个是买此物品的 “门槛”

本来正常做的,状态转移方程为   dp[j] = max(dp[j], dp[j -price[i]] + value[i]);

可是结果与测试数据对不上。。就反复找啊,原因在哪。后来发现原来我的数组推导过程不对。假如说第二组测试数据。 

5 10 5 的时候。我的背包容量为10,所以数组元素只有dp[10] = 5,可是当i++之后,下一个测试数据为 3 5 6。根据状态转移方程

dp[10] = max ( dp[10], dp[10 - 3] + 6 ) = 6. 可是买完第一个明明还能买第二个啊。但是如果先是买第二个再买第一个就数值正常。

就反复思考原因,没有办法。。。看了一眼提示,说按q-p排序就好。于是就反复想,为什么啊。。。没办法,又得看题解。。

杭电大神解释: 我们要保证的是,最先进行dp的结点必须是能开启dp[i]i的最小值的结点。因为只有这样才能保证DP的后效性。我们必须保证dp[j-price[i]]可以被赋值,它就要被先赋值

查了一下动态规划的特性

最优子结构:无论之前状态决策如何,局部最优解是构成全局最优解的必要条件

重叠子问题:。。。。

无后效性:动态规划法的最优解通常是由一系列最优决策组成的决策序列,最优子结构就是这些最优决策序列中的一个子序列,对于每个子序列再做最优决策会产生新的最优决策(子)序列,如果某个决策只受当前最优决策子序列的影响,而不受当前决策可能产生的新的最优决策子序列的影响,则可以理解这个最优决策具有无后效性。

刚开始看完全背包,完全背包应该也满足无后效性条件,因为它虽然可能多次选择前面的,但是它不改变前面的结果,只是改变当前决策的结果

自己理解:如果正常做就不满足无后效性的特性,假如按照第二组数据来看。就像上面说的,买完第一个还能买第二个,但是按照dp却不对,需要改变前一行的值才能使dp数组正确,这就是数组第一行决策受到了第二行决策影响,有后效性。所以要消除后效性。

按照大神的意思,应该是dp的正确性是因为它后面的依赖前面的也是正确的,

根据状态转移公式 dp[j] = max ( dp[j], dp[j - price[i]] + value[i]);

要保证dp后面正确,应该使dp[j - price[i]]不可能再被改变,dp[j-price[i]]式子中,j的值最小为want[i](商人只有你兜里的钱大于等于want[i]才卖给你东西)

所以,j -price[i] 的最小值为 want[i] - price[i].要保证 dp[j - price[i]]已经被赋值,就是保证前一行的want[i] - price[i]如果能被赋值一定要被赋值。

所以排序的顺序应该按照 want[i] - price[i]顺序排序才可以。

也就是按照q-p排序。

本题消除后效性方法:数组中下标小的数要先被赋值。以便后面访问此值是正确的


0 0
原创粉丝点击