HDU 3466 Proud Merchants(01背包/按limit-price从小到大排序)

来源:互联网 发布:我的域名如何使用 编辑:程序博客网 时间:2024/04/28 09:37

题目链接:
HDU 3466 Proud Merchants
题意:
n个商品和预算m元。每个商品有个价格price,购买限制limit和价值val,必须在手中剩余的金额大于limit时才能购买这件商品.(limit>price)问在预算条件下最多能购买的商品价值是多少?
分析:
典型的01背包。一开始是按照limit对商品排序,WA了好几发。看了discuss才知道原来要用limitpirce排序。
假设手中的钱足够买商品A和B的最少金额为total,那么显然total>limitAtotal>limitB
如果先买商品A的话,那还需要满足totalApriceA>=limitB,totalA=priceA+limitB
如果先买商品B的话,那还需要满足totalBpriceB>=limitA,即totalB=priceB+limitA
totalA<totalB,化简:limitBpriceB<limitApriceA.也就是limitprice大的先买。
再来考虑购买第i件商品时的状态转移方程(其中j是手中拥有金额数):

dp[j]=max(dp[j],dp[jgood[i].price]+good[i].val);

如果dp[j]=dp[jgood[i].price]+good[i].val,那么说明在手中有j元时在考虑前i件商品中首先购买了第i件商品则第i件商品应该是前i件商品中limitprice最大的,所以所有商品应该按照limitprice从小到大排序。

//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;}
0 0
原创粉丝点击