HDU 3535 AreYouBusy -- 分了组的混合背包

混合背包,还分组了 ,三种类型的set 最多取一个,最少取一个和没有限制
/*
	http://acm.hdu.edu.cn/showproblem.php?pid=3535 AreYouBusy
	混合背包,还分组了 ,三种类型的set  最多取一个,最少取一个和没有限制
*/

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

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

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

int dp[M][M];
int v[M]; // :value
int c[M]; // :cost

int main(){
	//freopen("in.txt","r",stdin);
	int n_set, max_cost;
	while(cin >> n_set >> max_cost){
		CLR(dp,0);
		for (int i = 1 ; i <= n_set ; i++){
			//0 stands for the sets that should choose at least 1 job to do, 
			//1 for the sets that should choose at most 1 ,
			//2 for the one you can choose freely
			int n_case, case_type;
			cin >> n_case >> case_type ;
			for(int j = 1 ; j <= n_case ; j++){
				cin >> c[j] >> v[j];
			}
			if(case_type == 0){
				for (int k = 0 ; k <= max_cost ; k++) // 这样确保最少放一个物品
					dp[i][k] = inf;
				for (int j = 1 ; j <= n_case ; j++)
				for (int k = max_cost ; k >= c[j] ; k--){
					//** 如果是第一次选,则一定能加入数组中
					//** 如果不是第一次选,则当做普通01背包处理
					dp[i][k] = Max(dp[i][k] , dp[i-1][k-c[j]] + v[j] , dp[i][k-c[j]] + v[j]);  
				}
			}else if(case_type == 1){
				for (int k = 0 ; k <= max_cost ; k++)
					dp[i][k] = dp[i-1][k]; // 为了保证全局最优解,初始化为上一次结果
				for (int j = 1 ; j <= n_case ; j++)
				for (int k = max_cost ; k >= c[j] ; k--){
					dp[i][k] = Max(dp[i][k], dp[i-1][k-c[j]] + v[j]);
				}
			}else{
				for (int k = 0 ; k <= max_cost ; k++)
					dp[i][k] = dp[i-1][k];
				for (int j = 1 ; j <= n_case ; j++)
				for (int k = max_cost ; k >= c[j] ; k--){
					dp[i][k] = Max(dp[i][k], dp[i-1][k-c[j]] + v[j], dp[i][k-c[j]] + v[j]);
				}
			}

		}
		int res = Max(dp[n_set][max_cost] , -1);
		cout << res << endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值