Proud Merchants---hdu3466(有01背包)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3466

与顺序有关的01背包。

如果一个物品p = 5,q = 7,一个物品p = 5,q = 9,如果先算第一个,那么当次只有7,8...m可以进行状态转移,装第二个物品的时候9,10..m进行转移,第二个物品转移就可以借用第一个物品的那些个状态,而第二个物品先转移,第一个再转移则不能。当然,还有价格有关,当限制一样价格不同时顺序就影响结果。一种组合的排序策略--限制又小价格又贵的先选,也就是q-p小的先选。为什么这样呢?A:p1,q1 B: p2,q2,先选A,则至少需要p1+q2的容量,而先选B则至少需要p2+q1,如果p1+q2>p2+q1,那么要选两个的话的就要先选A再选B,公式可换成q1-p1 > q2-p2,就按这样的方法排序最后的顺序就是最优的顺序。

该题要确保Q[i]-P[i]小的先被”挑选“,差值越小使用它的价值越大(做出的牺牲越小).

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
#define N 510
#define met(a, b) memset(a, b, sizeof(a))

int dp[N*10], n, m;

struct node
{
    int v, q, p, qp;
}a[N];
int cmp(node p, node q)
{
    return p.qp<q.qp;
}
int main()
{
    while(scanf("%d %d", &n, &m)!=EOF)
    {
        met(a, 0);
        met(dp, 0);
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d%d", &a[i].p, &a[i].q, &a[i].v);
            a[i].qp = a[i].q - a[i].p;
        }
        sort(a+1, a+n+1, cmp);
        for(int i=1; i<=n; i++)
        {
            for(int j=m; j>=a[i].q; j--)///dp[j]表示剩余j元钱所能购买物品的最大价值;
                dp[j] = max(dp[j], dp[j-a[i].p]+a[i].v);
        }
        printf("%d
", dp[m]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4994900.html