#include<iostream> #include<cstdio> using namespace std; const int MAXN = 1010; int n,m; //前i个物体,总体积是j 的最大总价值 int f[MAXN][MAXN]; int V[MAXN],W[MAXN]; int main(){ scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) cin >> V[i] >> W[i]; for(int i = 1; i <= n; i++){ for(int j = 0; j <= m; j++){ //要么不选 f[i][j] = f[i-1][j]; if(j >= V[i]){ //要么选择该背包,从f[i-1][j-v[i]]过来。 f[i][j] = max(f[i][j],f[i-1][j-V[i]]+W[i]); } } } int ans = 0; //在前n个物体中,选价值最大的一个 for(int i = 0; i <= m; i++){ ans = max(ans,f[n][i]); } printf("%d",ans); return 0; }
一维数组优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; const int MAXN = 1010; int f[MAXN]; int N,M; int V[MAXN],W[MAXN]; int main(){ scanf("%d%d",&N,&M); for(int i = 1; i <= N; i++) scanf("%d%d",&V[i],&W[i]); for(int i = 1; i <= N; i++) //从后往前推,保留i-1的状态 for(int j = M; j >= V[i]; j--){ f[j] = max(f[j],f[j-V[i]]+W[i]); } printf("%d",f[M]); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int N,M; const int MAXN = 1010; int f[MAXN][MAXN],V[MAXN],W[MAXN]; //转移方程,f[i][j] = max{f[i-1][j-k*V[i]+k*W[i]} //含义:可以在之前选完后,选择当前的[M/V[i]]个,取价值最大的那个。 int main(){ scanf("%d%d",&N,&M); for(int i = 1; i <= N; i++){ scanf("%d%d",&V[i],&W[i]); } for(int i = 1; i <= N; i++){ for(int j = 1; j <= M; j++){ for(int k = 0; k * V[i] <= j; k++){ f[i][j] = max(f[i][j],f[i-1][j-k*V[i]]+k*W[i]); } } } int ans = 0; for(int i = 1; i <= M; i++){ ans = max(ans,f[N][i]); } printf("%d",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 2e6+10; int dp[2020],V[MAXN],W[MAXN]; int main(){ int t = 0; int n,m; cin >> n >> m; for(int i = 0; i < n; i++){ int v,w,s; cin >> v >> w >> s; for(int k = 1; k <= s; k *= 2){ V[t] = v*k; W[t++] = w*k; s -= k; } if(s > 0) { V[t] = v*s; W[t++] = w*s; } } for(int i = 0; i < t ; i++){ for(int j = m; j >= V[i]; j--){ dp[j] = max(dp[j],dp[j-V[i]]+W[i]); } } cout << dp[m]; return 0; }
混合背包
有 N 种物品和一个容量是 V 的背包。
物品一共有三类:
第一类物品只能用1次(01背包); 第二类物品可以用无限次(完全背包); 第三类物品最多只能用 si 次(多重背包); 每种体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。 输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。