https://vjudge.net/contest/297216?tdsourcetag=s_pctim_aiomsg#problem/K
3(物品组数) 3(时间)
f[i,j]表示完成了前i件任务,
背包容量为j时所能达到的最大价值。
f[i-1,j-cost]+val;
2 1 最多选一件
2 5
3 8
2 0 至少选一件
1 0
2 1
3 2 自由选
4 3
2 1
1 1
#include<bits/stdc++.h> using namespace std; #define LL long long const int INF=0x3f3f3f3f; const int maxn=105; int cost[maxn]; int val[maxn]; int f[maxn][maxn]; int main() { int m,t; while(scanf("%d%d",&m,&t)==2) // 不写==2会超时!! { memset(f,0,sizeof(f)); for(int i=1; i<=m; i++) { int n,type; scanf("%d%d",&n,&type); for(int j=1; j<=n; j++) scanf("%d%d",&cost[j],&val[j]); if(type==0) { // 背包初始化要从0开始,而不是1 for(int j=0; j<=t; j++) f[i][j]=-INF; // 将新判断的一组物品,开始时不同背包容量的价值都初始化为负数,保证至少选入这个物品。 for(int j=1; j<=n; j++) for(int k=t; k>=cost[j]; k--) // k要倒着枚举,保证不重复选取。 { f[i][k]=max(f[i][k],f[i][k-cost[j]]+val[j]); f[i][k]=max(f[i][k],f[i-1][k-cost[j]]+val[j]); // 这两个写反了会错,为什么? } } else if(type==1) { for(int k=0; k<=t; k++) f[i][k]=f[i-1][k]; for(int j=1; j<=n; j++) for(int k=cost[j]; k<=t; k++)// 这个k可正序也可反序枚举 { f[i][k]=max(f[i][k],f[i-1][k-cost[j]]+val[j]); } } else { // 标准1维数组优化的01背包问题, for(int k=0; k<=t; k++) f[i][k]=f[i-1][k]; for(int j=1; j<=n; j++) for(int k=t; k>=cost[j]; k--) { f[i][k]=max(f[i][k],f[i][k-cost[j]]+val[j]); } } } int ans=max(f[m][t],-1); printf("%d\n",ans); } }
原文地址:https://www.cnblogs.com/dongdong25800/p/10789569.html
时间: 2024-10-22 01:03:13