1. 程式人生 > >HDU 3466 Proud Merchants【貪心 + 01背包】

HDU 3466 Proud Merchants【貪心 + 01背包】

ger HR init rst const #define tor people num

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 10
10 15 10
5 10 5
3 10
5 10 5
3 5 6
2 7 3
Sample Output
5
11

【分析】: 需要對物品按 qi-pi 的值從小到大排序,因為這樣可以保證每次更新的狀態值從小到大遞增,前面更新過的狀態不會影響後面更新的狀態。
每件物品有一個限制,只有當你當前現金大於qi的時候才會賣給你。

這題好好想了一下,跟之前做過的一道題有些類似。考慮簡化版,有兩個物品(p1,q1,v1),(p2,q2,v2),然後物品1先放的話,物品2就可以借助物品1產生的各種狀態來進行下一步轉移,而如果物品2的q2值過高,在這個[q2,m]的區間內都不存在物品1造成的新狀態的話,那麽物品1的狀態就沒有得到利用。而如果交換順序,先放了物品2,那麽顯然物品1就可以利用物品2產生的新狀態。

所以物品1能從物品2轉移的狀態區間其實是[min(q1+p2,m),m],物品2能從物品1轉移的狀態區間是[min(q2+p1,m),m]。所以盡可能地復用這個區間,讓區間小的先來,區間大的後來,這樣排序之後所有物品都能從前面的物品得到新狀態進行轉移。

而普通的01背包之所以不需要排序,是因為p1==q1,p2==q2,排序跟不排是一回事。這一類的dp題要註意後效性是否存在,如果存在通過改變順序之類的辦法來取消後效性。再有杭電上飯卡那題,qi恒定為5,所以也是需要排序的。

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,n,x) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int maxn =  1e5 + 5;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int n,m;
#define S 100000
#define M 200000
int dp[maxn];
struct node
{
    int p,q,v;
    int sub;
}a[maxn];
bool cmp(node x, node y)
{
    return x.sub < y.sub;
}
int main()
{
    while(cin >> n >> m)
    {
        ms(dp,0);
        for(int i=1;i<=n;i++) //但是如果你的錢少於Qi,他們會拒絕進行交易
        {
            cin >> a[i].p >> a[i].q >> a[i].v;
            a[i].sub = 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] = max(dp[j], dp[j-a[i].p]+a[i].v);
            }
        }
        cout << dp[m] << endl;
    }
    return 0;
}
/*
3 10
3 5 6
2 7 3
5 10 5
*/

HDU 3466 Proud Merchants【貪心 + 01背包】