现有 n 个物品,第 i 个物品的体积为 vi , 重量为 wi
求当前背包最多能装多大重量的物品?
数据范围: , , ,
进阶 :
10,2,[[1,3],[10,4]]
4
第一个物品的体积为1,重量为3,第二个物品的体积为10,重量为4。只取第二个物品可以达到最优方案,取物重量为4
10,2,[[1,3],[9,8]]
11
两个物品体积之和等于背包能装的体积,所以两个物品都取是最优方案
public class Solution { public int knapsack (int V, int n, int[][] vw) { return process(vw,0,0,0,V,n); } public int process(int[][] vw,int i,int alreadyW,int alreadyV,int V,int n) { if(alreadyV>V) { return 0; } if(i==n) { return alreadyW; } return Math.max(process(vw,i+1,alreadyW,alreadyV,V,n), process(vw,i+1,alreadyW+vw[i][1],alreadyV+vw[i][0],V,n)); } }试试递归,超时🌶
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 计算01背包问题的结果 * @param V int整型 背包的体积 * @param n int整型 物品的个数 * @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi * @return int整型 */ public int knapsack (int V, int n, int[][] vw) { // write code here int[][] dp = new int[n+1][V+1]; for(int i = 1 ; i <= n;i++){ for(int j = 1;j <= V;j++){ if(j < vw[i-1][0]){ dp[i][j] = dp[i-1][j]; }else{ dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-vw[i-1][0]]+vw[i-1][1]); } } } return dp[n][V]; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 计算01背包问题的结果 * @param V int整型 背包的体积 * @param n int整型 物品的个数 * @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi * @return int整型 */ public int knapsack2(int V, int n, int[][] vw) { if (V <= 0 || n <= 0 || vw.length != n) { return -1; } int[][] w = new int[n + 1][V + 1]; for (int i = n - 1; i >= 0; --i) { for (int j = 1; j <= V; ++j) { if (vw[i][0] <= j) { w[i][j] = Math.max(w[i + 1][j - vw[i][0]] + vw[i][1], w[i + 1][j]); } else { w[i][j] = w[i + 1][j]; } } } return w[0][V]; } public int knapsack(int V, int n, int[][] vw) { if (V <= 0 || n <= 0 || vw.length != n) { return -1; } int[] w = new int[V + 1]; for (int i = 0; i < n; ++i) { for (int j = V; j >= 1; --j) { if (vw[i][0] <= j) { w[j] = Math.max(w[j - vw[i][0]] + vw[i][1], w[j]); } } } return w[V]; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 计算01背包问题的结果 * @param V int整型 背包的体积 * @param n int整型 物品的个数 * @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi * @return int整型 */ public int knapsack (int V, int n, int[][] vw) { // write code here if (V == 0 || n == 0) { return 0; } int[][] dp = new int[V + 1][n + 1]; for (int i = 1; i <= V; i++) { for (int j = 1; j <= n; j++) { if (vw[j - 1][0] <= i) { dp[i][j] = Math.max(dp[i - vw[j - 1][0]][j - 1] + vw[j - 1][1], dp[i][j - 1]); } else { dp[i][j] = dp[i][j - 1]; } } } return dp[V][n]; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 计算01背包问题的结果 * @param V int整型 背包的体积 * @param n int整型 物品的个数 * @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi * @return int整型 */ public int knapsack (int V, int n, int[][] vw) { // write code here // 备注 1 参考文章 https://cloud.tencent.com/developer/article/1574605 // 备注 2 vw 的索引范围, vw[0,199][0,1] // 数组范围 +1, 简化代码, 比如不用 return dp[n-1][V-1], 且由于循环从 1 开始后续的 dp[i-1][j] 不用担心当 i==0 的时候 dp[-1][j] 会数组越界 int dp[][] = new int[n+1][V+1]; // 背包可容纳前 i (数量区间为[0,i]) 物品数量的最大(重量/价值) for(int i=1; i<=n; i++){ // 背包最大可容纳体积为 j for(int j=1; j<=V; j++){ // 先获取背包可容纳前 i-1 (数量区间为[0,i-1]) 物品数量的最大(重量/价值) int oldMax = dp[i-1][j]; // 新的物品的体积 int iV = vw[i-1][0]; // 新的物品的(重量/价值) int iW = vw[i-1][1]; // 如果新的物品的体积可以被背包容纳 if(j >= iV){ // 先计算好当体积为 j(当前背包最大可容纳体积) - iV(新的物品的体积) 时 背包可容纳前 i-1 (数量区间为[0,i-1]) 物品数量的最大(重量/价值)(已经在之前的步骤中计算好, 因为 0 < iV <= j, 所以 dp[i-1][j-iV] 已知) // 然后 + iW(新的物品的(重量/价值)) // 即可得到 背包可容纳前 i (数量区间为[0,i]) 物品数量的最大(重量/价值) int value = dp[i-1][j-iV] + iW; // 取最大值 if(value > oldMax){ dp[i][j] = value; }else{ // 说明性价比不高, 之前存在(重量/价值)较大且体积较小的物品 dp[i][j] = oldMax; } }else{ // 新的物品体积无法被背包容纳, 则背包可容纳的前i个物品数量的最大(重量/价值)等同于前i-1, 直接赋值 dp[i][j] = oldMax; } } } return dp[n][V]; } }
// dp[i][j]表示:对于前i个物品,当前背包的容量为j时,这种情况下可以装下的最大价值是dp[i][j]。 // 如果你没有把这第i个物品装入背包,那么很显然,最大价值dp[i][j]应该等于dp[i-1][j]。 // 你不装嘛,那就继承之前的结果。 // 如果你把这第i个物品装入了背包,那么dp[i][j]应该等于 // dp[i-1] [ j-vm[j-vm[i-1][0] ] + vm[i-1][1]。但还是需要和不装入进行大小比较,取价值最大的。 import java.util.*; public class Solution { public int knapsack (int V, int n, int[][] vw) { int v=V; int[][]dp=new int[n+1][v+1]; for(int i = 1; i<=n;i++){ for(int j = 1;j<=v;j++){ if(j<vw[i-1][0]){//注意此处为i-1 dp[i][j] = dp[i-1][j]; }else{ dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-vw[i-1][0]]+vw[i-1][1]); } } }return dp[n][v]; } }