题目链接:
HDU 3466 Proud Merchants
题意:
有
n
个商品和预算
分析:
典型的01背包。一开始是按照
limit
对商品排序,WA了好几发。看了discuss才知道原来要用
limit−pirce
排序。
假设手中的钱足够买商品A和B的最少金额为
total
,那么显然
total>limitA
且
total>limitB
,
如果先买商品A的话,那还需要满足
totalA−priceA>=limitB,
即
totalA=priceA+limitB
,
如果先买商品B的话,那还需要满足
totalB−priceB>=limitA
,即
totalB=priceB+limitA
,
令
totalA<totalB
,化简:
limitB−priceB<limitA−priceA.
也就是
limit−price
大的先买。
再来考虑购买第i件商品时的状态转移方程(其中j是手中拥有金额数):
dp[j]=max(dp[j],dp[j−good[i].price]+good[i].val);
如果 dp[j]=dp[j−good[i].price]+good[i].val, 那么说明在手中有j元时在考虑前i件商品中首先购买了第i件商品则第i件商品应该是前i件商品中 limit−price 最大的,所以所有商品应该按照 limit−price 从小到大排序。
//1444K 46MS
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N=510;
const int MAX_VAL=5010;
int n,m;
int dp[MAX_VAL];
struct Good{
int price,limit,val;
bool operator < (const Good a) const{
return (limit-price)<(a.limit-a.price);
}
}good[MAX_N];
int main()
{
//freopen("hdu3466in.txt","r",stdin);
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++){
scanf("%d%d%d",&good[i].price,&good[i].limit,&good[i].val);
}
sort(good+1,good+n+1);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
for(int j=m;j>=good[i].limit;j--){
dp[j]=max(dp[j],dp[j-good[i].price]+good[i].val);
}
}
printf("%d\n",dp[m]);
}
return 0;
}