奇怪的背包题目 - Proud Merchants

F - Proud Merchants
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

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
 

这题目就是说给出每个商品的pi,qi,vi,要有大于qi的钱才可以买该商品,该商品要实际花费pi元,而购买者自己估价该商品是vi元。

其实如果只有pi和vi,这就是很简单的01背包的问题,但是现在多了一个约束条件qi,这让这题截然不同。

让我最困惑的是例程中的第二个输入数据,如果我先买第二个商品,消耗了3元,剩下7元,那我就不可以买第一个商品了,只能买第三个,这样得出的结果是9,显然不是最优解,所以这个题目中购买商品需要有一个顺序,但是这个顺序我实在是一脸懵逼,只好靠别人的题解了。

思路大致是:

1,先不考虑顺序,这道题最大的麻烦是qi,我们所建立的01背包中,范围不再是pi - max了,而是qi - max,因为要有qi的钱才有资格去判断。

2,如果有pi = qi的情况,如果全是这种情况,这就是超级原始的01背包问题了,01背包中各个商品的加入原本是无序的。

3,终于要烧脑了,顺序怎么去想?只要想办法确定顺序,接下来就像无序那样建立01背包就行了。

人生的大起大落实在是太爽了,所以我们直接列举十分极限的数据来看看

依旧是只有10块钱,接下来商品:

1     10  1

1     10  10

1     1    1

10  10  10

后面两组情况是满足pi=qi的,理论上是无序的嘛,看前两组,第二组肯定是最好的,1元就能买到价格为10元的商品,当然这个前提是qi<=m,但是01背包中我们最后只要那个dp[n][m]这个角的数字,就是说第二组数据和第四组数据是相同的结果,所以我们再分析分析这两组数据。

这两组数据肯定是有不同的,不同在哪里呢?那就是pi的值。如果我们是比较第三组和第四组,pi也是不同的,其实要管qi吗?我们前面说这两组可以无序排序,在大前提下,他们的qi都是小于m的,所以这直接就是01背包是吧,在01背包里面if(j>=item[i].weight)     max(dp[j - item[i].weight] + item[i].value, dp[j]);   这个if判断就代表了他是weight到最大值m之间的循环。如果这个weight直接都大于m了,这个循环就直接跳出一层了。所以题目例程1当qi=15那种情况也要读入,只是我们会在后面跳出罢了。


#include<cstdio>
#include<algorithm> 
#include<cstring>
using namespace std;
int dp[5005];
struct trade
{
	int pi,qi,vi;
}goods[505];

int cmp(const void *a,const void *b)
{
	return ((*(trade *)a).qi-(*(trade *)a).pi)-((*(trade *)b).qi-(*(trade *)b).pi);
}

int main()
{
	int n,m,i,j;
	while(scanf("%d %d", &n, &m) != EOF)
	{
		for(i = 0; i < n; i++)
			scanf("%d %d %d", &goods[i].pi, &goods[i].qi, &goods[i].vi);
		qsort(goods, n , sizeof(goods[0]), cmp);
		for(j = 0; j <= m; j++)
		{
			dp[j] = 0;
		}
		for(i = 0; i < n; i++)
		{
			for(j = m; j >= goods[i].qi; j--)
			{
				if(dp[j - goods[i].pi] + goods[i].vi > dp[j])
					dp[j] = dp[j - goods[i].pi] + goods[i].vi;
			}
		}
		printf("%d\n", dp[m]);
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值