HDU 4501 小明系列故事——买年货 -- 分组揹包变体

/*
	http://acm.hdu.edu.cn/showproblem.php?pid=4501 小明系列故事——买年货
	题意:一个现金,一个优惠积分,都可以购买东西,并且只需要其中一个满足物品的消耗即可购买
	另外可以免费挑选1-5个商品赠送
	求最大的收益价值
	每种物品给出三个消费(现金消耗,积分消耗,免费权消耗),但是这三个消费并不是同时需要满足,
	所以我们可以将这个问题转化为一个分组揹包,每一个物品为一组,每组最多拿一个
	假设某一个物品的属性为 cost_money , point_cost , free_cost , value
	那么可以将这一组的物品理解为这三个:
	cost_money value
	point_cost value
	free_cost  value
	这样就可以用常规的分组揹包来解题了。注意最优状态的转移,一个物品不要多算了。

*/

#include <cmath>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define CLR(c,v) (memset(c,v,sizeof(c)))

template <typename _T>
_T Max(_T a,_T b){
	return a<b?b:a;
}
template <typename _T>
_T Max(_T a,_T b,_T c){
	return a<Max(b,c)?Max(b,c):a;
}
template <typename _T>
_T Min(_T a,_T b){
	return a>b?b:a;
}
template <typename _T>
_T Min(_T a,_T b,_T c){
	return a>Min(b,c)?Min(b,c):a;
}

const int inf = -(1<<30);
const int INF =  (1<<30);
const int M   =  1e2 + 5;

int dp[M][M][5+10]; // dp[1.2][cost1][cost2][free]

int main()
{
	//freopen("in.txt","r",stdin);
	int n,max_cost1 , max_cost2 , max_free;
	while(cin >> n >> max_cost1 >> max_cost2 >> max_free){
		CLR(dp,0);
		int free = 1, cost1, cost2, value;
		for(int i = 1 ; i <= n ; i++ ){
			cin >> cost1 >> cost2 >> value;
			for(int j = max_cost1; j >= 0 ; j--)
				for(int k = max_cost2 ; k >= 0 ; k--)
					for(int f = max_free ; f >= 0 ; f--){
						int v1 = (j >=cost1)?(dp[j -cost1][k][f]+value):(0);
						int v2 = (k >=cost2)?(dp[j][k -cost2][f]+value):(0);
						int v3 = (f >=    1)?(dp[j][k][f - 1]   +value):(0);
						dp[j][k][f] = Max(dp[j][k][f] , Max(v1,v2,v3) );
						//if(j>=cost1) // 这里不能这么写。因为此处的更新会导致一个物品放入了多次
						//	dp[j][k][f] = Max(dp[j][k][f], dp[j-cost1][k][f]+value); 
						//if(k>=cost2)
						//	dp[j][k][f] = Max(dp[j][k][f], dp[j][k-cost2][f]+value);
						//if(f>=free)
						//	dp[j][k][f] = Max(dp[j][k][f], dp[j][k][f-free]+value);
					}
		}
		cout << dp[max_cost1][max_cost2][max_free] << endl;
	}

	return 0;
}

/*
10 10 5 1
3 4 32
3 10 128
4 10 16
1 0 8
5 1 512
10 4 64
8 5 256
4 4 2
10 4 4
4 10 1
 = 1016
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章