当前位置:   article > 正文

01背包问题(通俗易懂,图例讲解)

01背包问题

问题描述:

01背包问题:一个容量为c的背包,现有n个物品可供选择。物品 i 的重量似乎 wi,其价值为 vi,如何选择放入背包的物品,使得背包中的物品总价值最大? 

01背包问题是一种动态规划问题。动态规划的核心就是状态转移方程,下面我们就用简单的例子来解决这个问题:

动态规划展示:

假设有3种水果可供选择:                   重量    价值                       背包重量为4kg

                                                榴莲      1kg     150元

                                                菠萝      3kg      200元

                                                草莓      4kg      400元

我们可以先从1kg背包开始算起,然后逐步到4kg背包。

下面我们来画图表来展示,横向代表背包重量,纵向代表水果种类;

 

我们先从第一行开始填,填完整后就找到了我们想要的结果;

第一行也就是我们需要将榴莲装入背包中,第一个格子是1kg的背包,而榴莲正好也是1kg,那我们就可以把它装进包里,价值为150元;

第二个单元格是2kg的背包,也可以装下1kg的榴莲,后面几个也一样,3kg的背包也装得下榴莲,现在你会觉得3kg背包也可以装下菠萝(3kg),但是现在我们考虑的只是第一行, 只有榴莲,可以这么理解现在只有榴莲可以放入背包,其他的水果都没有;所以3kg,4kg的背包都是装榴莲(1kg),其价值是150元。

 此时背包装的东西的最大价值是150元,这只是代表的只有榴莲的情况下的最大价值,也就是说只有榴莲的情况下,背包装的东西的最大价值是150元。

下面我们再加入菠萝,也就是说此时有榴莲,菠萝两种水果可以进行选择,现在我们继续计算:

因为菠萝重量为3kg,所以在第二行第一列(1kg背包)此处装不下菠萝,只能装榴莲,所以背包装榴莲,价值150元;

 

 同理,2kg的背包也装不下菠萝,所以2kg背包最大价值也是150元榴莲;

3kg背包可以装菠萝,也可以装榴莲,但菠萝价值大于榴莲价值,所以3kg背包装菠萝,最大价值为200元;

 

4kg背包可以同时装下榴莲和菠萝,其最大价值为350元;

然后我们继续加入草莓来计算 :

1-3kg背包和上面一样

 

 4kg背包有多种选择,一种是榴莲+菠萝组合,一种是草莓,

榴莲+菠萝 价值为350元,草莓价值为400元,所以4kg背包最大价值为400元,只装草莓;

 所以最终答案为装草莓,其最大价值为400元。

 逻辑分析

 

 上面的分析,其实都可以用这个公式来计算,当前单元格的值等于两个值相比的最大值,比如最后的结果,我们用上面单元格的350与当前商品的价格400+剩余空间可用价值0(因为没有可用空间了)相比,取最大值400;

再比如菠萝行4kg背包那个单元格的值等于:它上面单元格的值150与当前商品价格200+剩余空间可用价值(cell[1][4-3]=cell[1][1]=150)的和350元相比,取最大值350元。

 代码实现

  1. public static void main(String[] args) {
  2. Scanner scan = new Scanner(System.in);
  3. String str_0 = scan.nextLine();
  4. String[] line_list_0 = str_0.trim().split(" ");
  5. ArrayList<Integer> arr_temp = new ArrayList<>();
  6. for(int i = 0; i < line_list_0.length; i++){
  7. arr_temp.add(Integer.parseInt(line_list_0[i]));
  8. }
  9. int c = arr_temp.get(0);
  10. int n = arr_temp.get(1);
  11. ArrayList<ArrayList<Integer>> vector = new ArrayList<>();
  12. for(int i = 0; i < n; i++){
  13. String str_2 = scan.nextLine();
  14. String[] line_list_2 = str_2.trim().split(" ");
  15. ArrayList<Integer> temp_2 = new ArrayList<>();
  16. for(int j = 0; j < line_list_2.length; j++){
  17. temp_2.add(Integer.parseInt(line_list_2[j]));
  18. }
  19. vector.add(temp_2);
  20. }
  21. scan.close();
  22. int result = solution(c, n, vector);
  23. System.out.println(result);
  24. }
  25. public static int solution(int c, int n, ArrayList<ArrayList<Integer>> vector) {
  26. //n物品个数 c背包容量
  27. int weight[] = new int[n];//物品重量
  28. int value[] = new int[n];//物品价值
  29. for(int i=0;i<n;i++)
  30. {
  31. weight[i]=vector.get(i).get(0);
  32. value[i]=vector.get(i).get(1);
  33. }
  34. // 构造最优解的网格:3行4列
  35. int[][] maxValue = new int[n][c];
  36. for (int i = 0; i < n; i++) {
  37. for (int j = 0; j < c; j++) {
  38. maxValue[i][j] = 0;
  39. }
  40. }
  41. // 填充网格
  42. for (int i = 0; i < n; i++) {
  43. for (int j = 1; j <= c; j++) {
  44. if (i == 0) {
  45. maxValue[i][j - 1] = (weight[i] <= j ? value[i] : 0);
  46. } else {
  47. int topValue = maxValue[i - 1][j - 1]; // 上一个网格的值
  48. int thisValue = (weight[i] <= j ? // 当前商品的价值 + 剩余空间的价值
  49. (j - weight[i] > 0 ? value[i] + maxValue[i - 1][j - weight[i]] : value[i])
  50. : topValue);
  51. // 返回 topValue和thisValue中较大的一个
  52. maxValue[i][j - 1] = (topValue > thisValue ? topValue : thisValue);
  53. }
  54. }
  55. }
  56. return maxValue[n-1][c-1];
  57. }

有问题的可以留言询问

欢迎转载,转载请注明出处。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/332963
推荐阅读
相关标签
  

闽ICP备14008679号