背包包
取一组高达。它是该组,每个国家只能来自前一组状态,就拿分钟,并采取2种
至少拿,不要把它没有更多的选择,这是不dp[i][j]=dp[i-1][j]循环
免费拿,那01背包,借款包括不采取或采取一组从以前的,或采取选自
dp[i][j]它代表前i组。消费j可实现的最大时间值
早值福-1。它表示该状态不可达。为dp[0],早值福0,么都没有的时候最大的快乐值为0
另一个要注意的点c[k]可能为0。会影响到递推式的顺序
发现做这样的混合背包的题很有助于弄清楚各种背包间的差别和联系
#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=110;
const long long inf=-1u>>1;
typedef long long ll;
int c[maxn],g[maxn],dp[maxn][maxn];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,t,m,s;
while(scanf("%d%d",&n,&t)!=EOF){
memset(dp,-1,sizeof(dp));
memset(dp[0],0,sizeof(dp[0]));
for(int i=1;i<=n;i++){
scanf("%d%d",&m,&s);
for(int j=1;j<=m;j++) {
scanf("%d%d",&c[j],&g[j]);
}
if(s==0){
for(int k=1;k<=m;k++){
for(int j=t;j>=c[k];j--){
if(dp[i][j-c[k]]!=-1) dp[i][j]=max(dp[i][j],dp[i][j-c[k]]+g[k]);//注意c[k]可能为0。所以这两句不能交换顺序,要不然dp[i][j-c[k]]的值就被改变了
if(dp[i-1][j-c[k]]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-c[k]]+g[k]);
}
}
}
else if(s==1){
for(int j=0;j<=t;j++) dp[i][j]=dp[i-1][j];
for(int k=1;k<=m;k++){
for(int j=t;j>=c[k];j--){
if(dp[i-1][j-c[k]]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-c[k]]+g[k]);
}
}
}
else {
for(int j=0;j<=t;j++) dp[i][j]=dp[i-1][j];
for(int k=1;k<=m;k++){
for(int j=t;j>=c[k];j--){
if(dp[i][j-c[k]]!=-1) dp[i][j]=max(dp[i][j],dp[i][j-c[k]]+g[k]);
}
}
}
}
int ans=-1;
for(int i=0;i<=t;i++) ans=max(ans,dp[n][i]);
printf("%d\n",ans);
}
return 0;
}