这几天一直在想背包问题,昨天还有个学长专门讲了,但是还是不是很理解,今天我终于想通了背包问题,其实只要理解了这个思路,不管用什么语言,肯定是能编出来的。下面我就来介绍一下背包问题。

1.题目描述:

有如下5种物品,小明的书包最多只能装下8公斤的物品,小明特别贪心,思考怎么选择使自己书包能装下并且得到的价值最大。

物品1:6公斤     价值48元
物品2:1公斤     价值7元
物品3:5公斤     价值40元
物品4:2公斤     价值12元
物品5:1公斤     价值8元

2.解题思路:

其实我们正常思维,一般会想,我要尽量装满8公斤,把最大的价值求出来,可是这样的话,就需要用到递归,递归能解出来,只是算法难度高。但是什么是动态规划,动态规划就是逆着来,我要求装8公斤的物品怎么装使得价值最大。我可以先考虑装0公斤,最大价值,再考虑装1公斤最大价值,考虑装2公斤最大价值,装3公斤最大价值,把前面都记录下来。用另外一个temp[i][j]数组记录下来。i呢表示我现在出现的物品的数量,当i循环到最后一个数量的时候就结束了嘛。自己想象一下,我虽然有5件物品,先只给你一件,你判断能不能装下,能装下,那么你就看你装下这件物品,和不装下这件物品哪个价值高,那么记录下来即可。具体填下下面的表试下,真正会填表就差不多了

  1. 0 1 2 3 4 5 6 7 8
  2. 0 0 0 0 0 0 0 0 0
  3. 6 48 0 0 0 0 0 0 48 48 48
  4. 1 7 0 7 7 7 7 7 48 55 55
  5. 5 40 0 7 7 7 7 40 48 55 55
  6. 2 12 0 7 12 19 19 40 48 55 60
  7. 1 8 0 8 15 20 27 40 48 56 63

这个表是怎么来的呢?,举个例子,当我横着一排一排填,因为最开始只掉一件物品,开始掉重量是6的物品,到6的时候就能装下了,所以temp[1][6]=48,另外7,8也只有这一件物品填。所以还是一样的。

接下来掉第二个物品,掉下1这个物品了,1的价值是7,也就是temp[2][1] = 7。后面一直到temp[2][5]都是等于7。 重点重点来了,到了temp[2][6]的时候怎么办呢?我们的当然一看就是,我要选第一件物品,它的价值是48,可是选了第一件物品,背包就满了,就不能装第二件重量为1的物品了,所以temp[2][6] = 48。

我们人可以这样思考,关键就来了,关键就是怎么让计算机也可以这样思考呢,我们就需要用代码。其实仔细想想,我掉第二件物品了,判断如果不能装下,那么temp[2][j] = temp[2][j-1] //记住j表示的是我背包现在最大只能装j这么多,那既然这个物品装不下,那么当然不能装了。如果我当前物品重量小于j,那么我就可以选择是装还是不装呢?只要比较装还是不装哪个价值大就行了。如果不装的话价值这个时候的最大价值是不会变的,因为都不装嘛,也就是,temp[2][j] = temp[2-1][j] 。如果我装的话,关键是这个,还是到刚才的到第二件物品的价值为6的时候考虑,如果我装下重量1这个物品,temp[2][6] = temp[2-1][6 - 这个物品的重量] + 物品的价值  //

其实我   temp[2-1][6-这个物品重量]表示我还没装这个物品之前的价值腾出装这个物品的空间,然后加上这个物品的价值进行比较。关键是之前的每一个状态都用数组给记录下来了。关键代码先看一下,结合代码再理解

  1. for(int i=1;i<6;i++) {
  2. for(int j=1;j<9;j++) {
  3. if(w[i]<=j) {
  4. temp[i][j] = Math.max(temp[i-1][j], temp[i-1][j-w[i]]+v[i]); //其实就是比较物品选还是不选哪种价值大。
  5. }else {
  6. temp[i][j] = temp[i-1][j];//第i件物品不能放
  7. }
  8. }
  9. }

这个理解了,相信你自己也能编出这段代码来了。

3.代码示例

  1. package 背包问题;
  2.  
  3. import java.util.Scanner;
  4.  
  5. /*
  6. *
  7. 最多可以放8公斤的物品
  8. 物品1:6公斤 价值48元
  9. 物品2:1公斤 价值7元
  10. 物品3:5公斤 价值40元
  11. 物品4:2公斤 价值12元
  12. 物品5:1公斤 价值8元
  13.  
  14. 0 1 2 3 4 5 6 7 8
  15. 0 0 0 0 0 0 0 0 0
  16. 6 48 0 0 0 0 0 0 48 48 48
  17. 1 7 0 7 7 7 7 7 48 55 55
  18. 5 40 0 7 7 7 7 40 48 55 55
  19. 2 12 0 7 12 19 19 40 48 55 60
  20. 1 8 0 8 15 20 27 40 48 56 63
  21.  
  22. */
  23. public class Test01 {
  24. public static void main(String[] args) {
  25. //定义一个数组a[i][j] = a[i] i表示当前物品的序号选上,j表示这个位置能得到的最大值
  26. //选或者不选动态规划
  27. Scanner scn = new Scanner(System.in);
  28. int [] w = new int[6];//表示每件物品的重量
  29. int [] v = new int[6];//表示每件物品的价值
  30. for(int i=1;i<6;i++) {
  31. w[i] = scn.nextInt();//输入重量
  32. v[i] = scn.nextInt();//输入价值
  33. }
  34.  
  35. int [][] temp = new int[6][9]; //8表示背包最多能放8公斤的重量
  36. for(int j=0;j<9;j++) { //初始化每一行
  37. temp[0][j] = 0;
  38. }
  39. for(int i=1;i<6;i++) { //背包的重量为0的时候,最大价值肯定是0
  40. temp[i][0] = 0;
  41. }
  42.  
  43. for(int i=1;i<6;i++) { //从第一个物品开始选,记录我选了前面出现的物品,背包重量从1-8的能选上的最大的值
  44. for(int j=1;j<9;j++) { //当i循环到最后一层5的时候,也就是得到了,我5件物品都选上的时候的最大的值
  45. if(w[i]<=j) { //重量比这个状态小,那么就能放。 那么就只是放与不放,看是放重量大,还是不放重量大
  46. temp[i][j] = Math.max(temp[i-1][j], temp[i-1][j-w[i]]+v[i]);
  47. }else {
  48. temp[i][j] = temp[i-1][j];//第i件物品不能放
  49. }
  50. }
  51. }
  52. for(int i=0;i<6;i++) {
  53. for(int j=0;j<9;j++) {
  54. System.out.printf("%-5d",temp[i][j]);
  55. }
  56. System.out.println();
  57. }
  58. }
  59. }

java实现最通俗易懂的01背包问题的更多相关文章

  1. 01背包问题(Java实现)

    关于背包问题,百度文库上有崔添翼大神的<背包九讲>,不明的请移步查看.这里仅介绍最基本的01背包问题的实现. public class Knapsack { private final i ...

  2. HDU 2602 Bone Collector(经典01背包问题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2602 Bone Collector Time Limit: 2000/1000 MS (Java/O ...

  3. 【ACM】Knapsack without repetition - 01背包问题

    无界背包中的状态及状态方程已经不适用于01背包问题,那么我们来比较这两个问题的不同之处,无界背包问题中同一物品可以使用多次,而01背包问题中一个背包仅可使用一次,区别就在这里.我们将 K(ω)改为 K ...

  4. 动态规划专题 01背包问题详解 HDU 2546 饭卡

    我以此题为例,详细分析01背包问题,希望该题能够为大家对01背包问题的理解有所帮助,对这篇博文有什么问题可以向我提问,一同进步^_^ 饭卡 Time Limit: 5000/1000 MS (Java ...

  5. 【优化算法】变邻域搜索算法解决0-1背包问题(Knapsack Problem)代码实例 已

    01 前言 经过小编这几天冒着挂科的风险,日日修炼,终于赶在考试周中又给大家更新了一篇干货文章.关于用变邻域搜索解决0-1背包问题的代码.怎样,大家有没有很感动? 02 什么是0-1背包问题? 0-1 ...

  6. 01背包问题_回溯法&分支限界法

    package 分支限界法; import java.util.LinkedList; import java.util.Scanner; /*01背包问题*/ public class ZOPack ...

  7. DP动态规划之01背包问题

    目录 问题描述 问题分析 问题求解 Java代码实现 优化方向一:时间方面:因为是j是整数是跳跃式的,可以选择性的填表. 思考二:处理j(背包容量),w(重量)不为整数的时候,因为j不为整数了,它就没 ...

  8. 201871030108-冯永萍 实验二 个人项目— D{0-1}背包问题项目报告

    项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs.com/nwnu-dai ...

  9. Java多线程系列--“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...

随机推荐

  1. 静态和全局变量的作用域zz

    全局变量和静态变量的存储方式是一样的,只是作用域不同.如果它们未初始化或初始化为0则会存储在BSS段,如果初始化为非0值则会存储在DATA段,见进程的地址空间分配一文. 静态变量的作用域是当前源文件, ...

  2. bean作用域

    https://blog.csdn.net/u011468990/article/details/49995865 其中比较常用的是singleton和prototype两种作用域.对于singlet ...

  3. flask 之 rabbit

    使用pika库操作rabbit 查找whereis rabbitmq-server 启动/usr/sbin/rabbitmq-server & 打印了一些rabbitmq服务状态信息,包括内存 ...

  4. 理解加密算法——创建CA机构,签发证书并开始TLS通信

    1 不安全的TCP通信 普通的TCP通信数据是明文传输的,所以存在数据泄露和被篡改的风险,我们可以写一段测试代码试验一下,NODE.JS代码: TCP Server: const net=requir ...

  5. Servlet 前端后台交互

    一. URL地址传值   1.1. 地址传值 http://localhost:8080/xj/123/name.json servlet 对应接受方法 @RequestMapping(value=& ...

  6. 数据结构与算法JavaScript描述——队列

    注:澄清一个bug: /** * 删除队首的元素: */ function dequeue(){ return this.dataStore.shift(); } 应该有return:   队列是一种 ...

  7. 将新浪博客里的表情包存入MySQL数据库不完整版本一堆可能用到的散乱代码

    header = {'Cookie': 'SINAGLOBAL=7368591819178.463.1491810091070; ALF=1558832450; SCF=Ajrc1sxuwynVIu_ ...

  8. 009:JSON

    一. MySQL JSON类型 1. JSON介绍 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级 ...

  9. Centos7 可执行程序自定义为系统服务

    systemctl的使用相比以往系统服务的/etc/init.d的启动脚本的方式变动也比较大,但变的更简单更易用了,同firewalld一样,运行原理一目了然,对于初学者来说,只要做过一两次练习,就能 ...

  10. Collection集合学习(二)———List接口与具体实现

    二.List接口: 一个可以包含重复元素的Collection,List中的元素不会自动排序,元素顺序由添加时的顺序决定. 具体实现类包括Vector(线程安全的),ArrayList,LinkedL ...