题目链接:(—_—) zZ
题目大意:有n种工作的集合, 每种集合有一种类型, 0为最少在这个集合中选一个工作, 1为最多在这个集合中选一个工作, 2为随便选, 做每个工作要花一定的时间和得到一定的幸福度, 求在t时间内获得的最大幸福度
思路:类型为0时是分组背包的变形 , 为1时就是分组背包, 为2是为0-1背包,分别根据背包类型求出就可
Ps:无限wa
code:
#include <stdio.h> #include <string.h> struct node { int t, h; }pack[5][100002]; int c = 0, n = 0, t = 0,dp[102][102], num[5][102], index1[5], ind[102]; void zeropack( int in, int start)//至少选一个 { int i = 0, j = 0, k = 0, tpval = 0; for(i = 0; i<num[0][in]; i++) { for(j = t; j>=pack[0][start+i].t; j--) { if(dp[c][j-pack[0][start+i].t] != -1) dp[c][j] = dp[c][j]>dp[c][j-pack[0][start+i].t]+pack[0][start+i].h? dp[c][j]:dp[c][j-pack[0][start+i].t]+pack[0][start+i].h; if(dp[c-1][j-pack[0][start+i].t] != -1) dp[c][j] = dp[c][j]>dp[c-1][j-pack[0][start+i].t]+pack[0][start+i].h? dp[c][j]:dp[c-1][j-pack[0][start+i].t]+pack[0][start+i].h; } } } void onepack(int in, int start)//最多选一个 分组背包问题 { int i = 0, j = 0, k = 0, tpval = 0; for(i = 0; i<=t; i++) dp[c][i] = dp[c-1][i]; for(i = t; i>=0; i--) { for(j = 0; j<num[1][in]; j++) if(pack[1][start+j].t<=i && dp[c-1][i-pack[1][start+j].t] != -1) dp[c][i] = dp[c][i]>dp[c-1][i-pack[1][start+j].t]+pack[1][start+j].h? dp[c][i]:dp[c-1][i-pack[1][start+j].t]+pack[1][start+j].h; } } void twopack(int in, int start)//0-1背包 { int i = 0, j =0, k = 0, tpval = 0; for(i = 0; i<=t; i++) dp[c][i] = dp[c-1][i]; for(i = 0; i<num[2][in]; i++) { for(j = t; j>=pack[2][start+i].t; j--) { if(dp[c][j-pack[2][start+i].t] != -1 ) dp[c][j] = dp[c][j]>dp[c][j-pack[2][start+i].t]+pack[2][start+i].h? dp[c][j]:dp[c][j-pack[2][start+i].t]+pack[2][start+i].h; } } c++; } int main() { int i = 0, j = 0, m = 0, s = 0, start = 0, ans = -1; while(scanf("%d %d", &n, &t) != EOF) { c = 1; memset(index1, 0, sizeof(index1)); memset(ind, 0, sizeof(ind)); memset(dp, -1, sizeof(dp)); for(i = 0; i<=t; i++) dp[0][i] = 0; for(i = 0; i<n; i++) { scanf("%d %d", &m, &s); num[s][index1[s]++] = m;//index1[s]表示有多少类为s的组 for(j =0; j<m; j++, ind[s]++) { scanf("%d", &pack[s][ind[s]].t); scanf("%d", &pack[s][ind[s]].h); } } start = 0; for(j = 0; j<index1[0]; j++)//一共有多少组类属于0的 { zeropack(j, start); start += num[0][j]; c++; } start = 0; for(j = 0; j<index1[1]; j++) { onepack(j, start); start += num[1][j]; c++; } start = 0; for(j = 0; j<index1[2]; j++) { twopack(j, start); start += num[2][j]; } printf("%d\n", dp[c-1][t]); } return 0; }