HDU3466 Proud Merchants 01背包

10 篇文章 0 订阅

Proud Merchants

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 8958 Accepted Submission(s): 3766

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

Sample Output
5
11

问题连接

问题描述

有N个商人卖货物,每个商人只卖一件货物,货物的价格为p,价值为v,但是这里的商人比较自负,如果你手头没有q那么他会拒绝和你交易。有M的货币,问能获得的最大价值是多少。

问题分析

每件货物要么拿要么不拿,所以是01背包。但是要预先处理一下数据,因为可能出现这种情况:有M的钱,可以先买商人i的货物(相关参数为Pi,Qi,Vi),再买商人j的货物(Pj,Qj,Vj),而如果先买j的货物就买不了i的货物,如果有这种情况且j放在i的前面,那么就会出错,这种就是有后效性的,要消除后效性才能使用动态规划。
对于上面的情况不难列出:
M>=Qi , M-Pi>=Qj , M>=Qj , M-Pj<Qi.
推导:
Pi-M<=-Qj , M-Pj<Qi;
Pi-Pj<Qi-Qj;
Qi-Pi>Qj-Pj;
也就是说当Qi-Pi>Qj-Pj时就可能会有上面的情况,这时应该先买i再卖j,又01背包的拿货物的顺序是先空出空间再看是否更新,也就是说是先拿当前的货物再按之前的DP结果拿货物,所以,在排序的时候应该让i在j的后面。

程序如下

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=505;
const int M=5005;

int dp[M];

struct group{
	int p,q,v,gap;
}item[N];

bool cmp(group&obj1,group&obj2){
	return obj1.gap<obj2.gap;
}
int main(){
	int n,m,i,j;
	while(scanf("%d %d",&n,&m)!=EOF){
	for(i=0;i<n;i++){
		scanf("%d %d %d",&item[i].p,&item[i].q,&item[i].v);
		item[i].gap=item[i].q-item[i].p;//记录差值,减少减法运算次数 
	}
	
	sort(item,item+n,cmp);//排序 
	
	memset(dp,0,sizeof(dp));
	for(i=0;i<n;i++){//01背包 
		for(j=m;j>=item[i].q;j--){
			if(dp[j]<dp[j-item[i].p]+item[i].v){
				dp[j]=dp[j-item[i].p]+item[i].v;
			}
		}
	}
	printf("%d\n",dp[m]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值