思路:
分为3种不同的情况:
(1)fg = 0,至少一个的01背包,初始化所有值为-INF,表示不存在这种情况,
多选一个
dp[i][j] = dp[i][j-cur[i].ci[p]]+cur[i].gi[p];
从上一次选一个
dp[i][j] = dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p];
(2)fg = 1,至多一个的01背包
从上一次选一个
dp[i][j] = dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p];
(3)fg = 2,随便选一个的01背包,就是简单的01背包
dp[i][j] = dp[i][j-cur[i].ci[p]]+cur[i].gi[p];
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 120;
const int INF = 1e9+10;
int dp[maxn][maxn],n,T;
struct Node{
int fg,m;
int ci[maxn],gi[maxn];
}cur[maxn];
int main(void){
while(~scanf("%d%d",&n,&T)){
for(int i=0;i<maxn;i++) dp[i][0] = dp[0][i] = 0;
for(int i=1;i<=n;i++){
scanf("%d%d",&cur[i].m,&cur[i].fg);
for(int j=1;j<=cur[i].m;j++) scanf("%d%d",&cur[i].ci[j],&cur[i].gi[j]);
}
for(int i=1;i<=n;i++){
if(cur[i].fg==0){ //至少1个01
for(int j=0;j<=T;j++) dp[i][j] = -INF;
for(int p=1;p<=cur[i].m;p++){
for(int j=T;j>=cur[i].ci[p];j--){
if(dp[i][j-cur[i].ci[p]]+cur[i].gi[p]>dp[i][j])
dp[i][j] = dp[i][j-cur[i].ci[p]]+cur[i].gi[p];
if(dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p]>dp[i][j])
dp[i][j] = dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p];
}
}
}
else if(cur[i].fg==1){ //至多一个01
for(int j=0;j<=T;j++) dp[i][j] = dp[i-1][j];
for(int p=1;p<=cur[i].m;p++){
for(int j=T;j>=cur[i].ci[p];j--)
if(dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p]>dp[i][j])
dp[i][j] = dp[i-1][j-cur[i].ci[p]]+cur[i].gi[p];
}
}
else if(cur[i].fg==2){ //01背包
for(int j=0;j<=T;j++) dp[i][j] = dp[i-1][j];
for(int p=1;p<=cur[i].m;p++){
for(int j=T;j>=cur[i].ci[p];j--)
if(dp[i][j-cur[i].ci[p]]!=-1&&dp[i][j-cur[i].ci[p]]+cur[i].gi[p]>dp[i][j])
dp[i][j] = dp[i][j-cur[i].ci[p]]+cur[i].gi[p];
}
}
}
printf("%d\n",dp[n][T]>-1?dp[n][T]:-1);
}
return 0;
}