你有一个背包,最多能容纳的体积是V。
现在有n个物品,第i个物品的体积为
,价值为
。
(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?
第一行两个整数n和V,表示物品个数和背包体积。接下来n行,每行两个数和
,表示第i个物品的体积和价值。
输出有两行,第一行输出第一问的答案,第二行输出第二问的答案,如果无解请输出0。
3 5 2 10 4 5 1 4
14 9
装第一个和第三个物品时总价值最大,但是装第二个和第三个物品可以使得背包恰好装满且总价值最大。
3 8 12 6 11 8 6 8
8 0
装第三个物品时总价值最大但是不满,装满背包无解。
要求O(nV)的时间复杂度,O(V)空间复杂度
#include <limits.h> #include <stdio.h> #include <string.h> int max(int a, int b) { return (a > b ? a : b); } int main() { int n, m; scanf("%d %d", &n, &m); int v[n + 1], w[n + 1], dp[m + 1]; v[0] = 0, w[0] = 0; for (int i = 1; i <= n; i++) { scanf("%d %d", &v[i], &w[i]); } memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) { for (int j = m; j >= v[i]; j--) { dp[j] = max(dp[j], dp[j - v[i]] + w[i]); } } printf("%d\n", dp[m]); for (int i = 1; i <= m; i++) { dp[i] = INT_MIN; } for (int i = 1; i <= n; i++) { for (int j = m; j >= v[i]; j--) { dp[j] = max(dp[j], dp[j - v[i]] + w[i]); } } printf("%d",(dp[m]>0?dp[m]:0)); return 0; }
#include "stdio.h" #include "stdlib.h" // 抄榜一大佬的 int max(int a,int b) { return a>b?a:b; } int main() { int n,V; // 输入n, V scanf("%d%d",&n,&V); // 价值和重量 int *vi=(int*)malloc(sizeof(int)*n); int *wi=(int*)malloc(sizeof(int)*n); for(int i=0;i<n;i++) { scanf("%d %d",&vi[i],&wi[i]); } // dp内存 int *dp=(int*)malloc(sizeof(int)*(V+1)); dp[0]=0 ; // 小细节,这里不设置为0. 无法计算出正确答案 for(int i=1;i<V+1;i++) dp[i]=0x80000000; // -2147483648 int max_dp=0; // 第一问答案 int j; // 从上往下,从右往左:因为物品都只能用一次 for(int i=1;i<=n;i++) { for(j=V;j>=vi[i-1];j--) { dp[j]=max(dp[j-vi[i-1]]+wi[i-1],dp[j]); if(dp[j]>max_dp) // 第一问答案就是恰好在某个容量时,可以达到的最大价值。一直记录最大值,就可以得到 max_dp=dp[j]; // 记录更新第一问答案 } } printf("%d\n",max_dp); max_dp=dp[V]; free(dp); if(max_dp<0) printf("0"); else printf("%d",max_dp); }