题目链接:(—_—) 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;
}