HDU3535AreYouBusy(分组背包)
http://acm.hdu.edu.cn/showproblem.php?pid=3535
分组背包,每一组加了以下三个限制
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
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <ctime> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define MAX(a,b) (a > b ? a : b) #define MIN(a,b) (a < b ? a : b) #define mem0(a) memset(a,0,sizeof(a)) #define mem1(a) memset(a,-1,sizeof(a)) #define lson k<<1, L, mid #define rson k<<1|1, mid+1, R typedef long long LL; const double eps = 1e-12; const int MAXN = 100005; const int MAXM = 500005; int n, T, m, s; int DP[110][110]; int cost[110], val[110]; int main() { while(~scanf("%d%d", &n, &T)) { for(int i=0;i<=T;i++) DP[0][i]=0; for(int i=1;i<=n;i++) { scanf("%d%d", &m, &s); for(int j=0;j<m;j++) scanf("%d%d", &cost[j], &val[j]); if(s==0) { for(int k=0;k<=T;k++) DP[i][k] = -INF;// 这样确保最少放一个物品 for(int j=0;j<m;j++) for(int k=T;k>=cost[j];k--) { //** 如果是第一次选,则一定能加入数组中 //** 如果不是第一次选,则当做普通01背包处理 DP[i][k] = max(DP[i][k], max(DP[i][k-cost[j]]+val[j], DP[i-1][k-cost[j]]+val[j])); } } else if(s==1) { // 为了保证全局最优解,初始化为上一次结果 for(int k=0;k<=T;k++) DP[i][k] = DP[i-1][k]; for(int j=0;j<m;j++) for(int k=T;k>=cost[j];k--) { DP[i][k] = max(DP[i][k], DP[i-1][k-cost[j]]+val[j]); } } else if(s==2) { for(int j=0;j<=T;j++)DP[i][j] = DP[i-1][j]; for(int j=0;j<m;j++) for(int k=T;k>=cost[j];k--) { DP[i][k] =max(DP[i][k], max(DP[i-1][k-cost[j]]+val[j], DP[i][k-cost[j]]+val[j])); } } } printf("%d\n", max(DP[n][T], -1)); } return 0; }