混合背包,还分组了 ,三种类型的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;
}