01背包问题

给定一个容量为C的背包,重量为weight,价值为value的石头,求背包能容纳的最大价值。

weight = [1, 2, 3]
value = [6, 10 ,12]
C = 5输出:22
背包中放入一个重量为3的石头和一个重量为2的石头
value = 10 + 12 = 22.

递归

 public int findRes(int[] weight, int[] value, int capcity) {if(weight.length != value.length) return 0;if(capcity < 0)return 0;if(weight.length == 0)return 0;return helper(weight, value, capcity, weight.length - 1);}//f(n, c)  考虑[0 - n] 中背包重量为c的最优解//状态转移方程为  f(n, c) = Math.max(不考虑最后一个石头, 最后一个石头的价值 + 考虑最后一个石头后剩余背包容量的最大值);//状态转移方程为  f(n, c) = Math.max(f(n - 1, c), v[n] + f(n - 1, c - w[n]));private int helper(int[] weight, int[] value, int capcity, int index) {//如果背包中if(index < 0 || capcity <= 0)return 0;int res = helper(weight, value, capcity, index - 1);if(capcity >= weight[index])res = Math.max(res, value[index] + helper(weight, value, capcity - weight[index], index - 1));return res;}

不难发现此种解法会有重叠计算的问题

记忆化搜索-自下而上

我们开辟一个空间存储之前计算的结果

 public int findRes2(int[] weight, int[] value, int capcity) {if(weight.length != value.length) return 0;if(capcity < 0)return 0;if(weight.length == 0)return 0;//行:是否考虑该位置的石头 0:只考虑第一个  1:考虑1  n:考虑n//列:背包剩余容量int memo[][] = new int[weight.length][capcity + 1];for(int i = 0; i < memo.length; i ++)Arrays.fill(memo[i], - 1);return helper2(weight, value, capcity, weight.length - 1, memo);}//f(n, c)  考虑[0 - n] 中背包重量为c的最优解//状态转移方程为  f(n, c) = Math.max(不考虑最后一个石头, 最后一个石头的价值 + 考虑最后一个石头后剩余背包容量的最大值);//状态转移方程为  f(n, c) = Math.max(f(n - 1, c), v[n] + f(n - 1, c - w[n]));private int helper2(int[] weight, int[] value, int capcity, int index, int[][] memo) {//如果背包中if(index < 0 || capcity <= 0)return 0;if(memo[index][capcity] != -1)return memo[index][capcity];int res = helper2(weight, value, capcity, index - 1, memo);if(capcity >= weight[index])res = Math.max(res, value[index] + helper2(weight, value, capcity - weight[index], index - 1, memo));memo[index][capcity] = res;return res;}

动态规划-自上而下

 //时间复杂度为O(C * n) 其中C为背包容量,n为石头个数//空间复杂度为O(C * n) 其中C为背包容量,n为石头个数private int findRes3(int[] weight, int[] value, int capcity) {if(weight.length != value.length) return 0;if(capcity <= 0)return 0;if(weight.length == 0)return 0;//行:是否考虑该位置的石头 0:只考虑第一个  1:考虑1  n:考虑n//列:背包剩余容量int memo[][] = new int[2][capcity + 1];//base casefor(int i = 0; i <= capcity; i ++) {//只考虑第一个,只要容量满足,就可以放入if(weight[0] <= i)memo[0][i] = value[0];}for(int i = 1; i < weight.length; i ++) {for(int j = 0; j <= capcity; j ++) {int tmp = i ;//不考虑当前位置的石头memo[i][j] = memo[i - 1][j];//考虑且要放得下if(j >= weight[i])memo[i][j] = Math.max(memo[i][j], value[i] + memo[i - 1][j - weight[i]]);}}return memo[weight.length - 1][capcity];}

优化

可以发现i行数据依赖于i - 1行数据,所以我们只要重用空间就可以只使用2行记录状态。

 //时间复杂度为O(C * n) 其中C为背包容量,n为石头个数//空间复杂度为O(C * 2) 其中C为背包容量private int findRes4(int[] weight, int[] value, int capcity) {if(weight.length != value.length) return 0;if(capcity <= 0)return 0;if(weight.length == 0)return 0;//行:是否考虑该位置的石头 0:只考虑第一个  1:考虑1  n:考虑n//列:背包剩余容量int memo[][] = new int[2][capcity + 1];//base casefor(int i = 0; i <= capcity; i ++) {//只考虑第一个,只要容量满足,就可以放入if(weight[0] <= i)memo[0][i] = value[0];}for(int i = 1; i < weight.length; i ++) {for(int j = 0; j <= capcity; j ++) {int tmp = i ;//不考虑当前位置的石头 [0]的位置放偶数 [1]的位置放奇数memo[i & 1][j] = memo[(i - 1) & 1][j];//考虑且要放得下if(j >= weight[i])memo[i & 1][j] = Math.max(memo[i & 1][j], value[i] + memo[(i - 1) & 1][j - weight[i]]);}}return memo[(weight.length - 1) & 1][capcity];}

最佳

在此深入可以发现,每一行数据只依赖上一行数据的左边数据,所以我们可以将数据存储实现在一行上。

 //时间复杂度为O(C * n) 其中C为背包容量,n为石头个数//空间复杂度为O(C) 其中C为背包容量private int findRes5(int[] weight, int[] value, int capcity) {if(weight.length != value.length) return 0;if(capcity <= 0)return 0;if(weight.length == 0)return 0;//行:是否考虑该位置的石头 0:只考虑第一个  1:考虑1  n:考虑n//列:背包剩余容量int memo[] = new int[capcity + 1];//base casefor(int i = 0; i <= capcity; i ++) {//只考虑第一个,只要容量满足,就可以放入if(weight[0] <= i)memo[i] = value[0];}//右边数据依赖于左边数据,所以只要开辟O(C)空间for(int i = 1; i < weight.length; i ++) {for(int j = capcity; j >= weight[i]; j --) {memo[j] = Math.max(memo[j], value[i] + memo[j - weight[i]]);}}return memo[capcity];}

测试main函数

 public static void main(String[] argc){int[] weight = new int[]{1, 2, 3};int[] value = new int[]{6, 10, 12};int res = new Pakage01().findRes(weight, value, 5);System.out.println(res);}

01背包问题解法及优化相关推荐

  1. 01背包问题关于空间优化的讨论

    今天学习到了dp(其实以前就学过,不过没学好),再次看到背包问题的时候,突然意识到空间优化过后,他对剩余体积的遍历方式改变了! 看看背包九讲上的伪代码: 这是优化空间之前的 这是优化空间之后的.也是想 ...

  2. 0-1背包问题的一维数组优化解析

    [问题描述] 常见的0-1背包问题,多使用二维数组来实现.二维数组实现时,常用的状态转移方程为: c[i][j]=c[i-1][j], j<vol[i] c[i][j]=max(c[i-1][j ...

  3. 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)

    01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷.防晒霜.雨伞.水杯等等,但书包装不下所有物品,因此我们必须有所取舍.那么通常 ...

  4. 动态规划背包问题详解(二)---0-1背包问题

    /**  * 对于技术面试,你还在死记硬背么?  * 快来"播"沙糖橘吧,  * 用视频案例为你实战解读技术难点  * 聚焦Java技术疑难点,实战视频为你答疑解惑  * 越&qu ...

  5. 01背包问题和完全背包问题

    内容仅供自己复习使用 整数划分 小A点菜 这两个问题十分类似,一个是01背包.一个是完全背包. 整数划分因为一个数字可以多选,所以是完全背包问题.点菜问题只能选或者不选,所以是01背包问题. 未优化版 ...

  6. 0-1背包问题(一维数组解法)

    0-1背包问题: 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 这个问题的特点是:每种物品只 ...

  7. 0-1背包问题动态规划模型的Python解法

    0-1背包问题动态规划模型的Python解法 1.01背包问题 2.Python解决方案 3.01背包问题例题 1.01背包问题 背包问题(Knapsack problem)是一种组合优化的NP完全问 ...

  8. 【动态规划笔记】01背包问题及优化

    dp[i][j]:在前i件物品中选出若干件,放入容量为j的背包,能获得的最大价值 考虑第i件物品 [拿]  还是  [ 不拿 ] (1)j < c[i] 时,背包容量为j,而第i件物品重量大于j ...

  9. #动态规划 0-1背包问题空间复杂度优化

    上一个版本的0-1背包代码的复杂度:时间复杂度O(n*C)空间复杂度O(n*C) 优化思路如下: 0-1背包问题: F(n,C)考虑将n个物品放入背包为C 的背包,使得价值最大. 状态转移方程:F(i ...

  10. 算法设计 - 01背包问题的状态转移方程优化,以及完全背包问题

    01背包问题的一维状态转移方程的推导 前提摘要 前面这篇博客中: 算法设计 - 01背包问题_伏城之外的博客-CSDN博客 我们已经推导出了01背包问题的二维数组dp状态转移方程公式: 假设有N种不同 ...

最新文章

  1. centos7上搭建http服务器以及设置目录访问
  2. 【RocketMQ工作原理】indexFile
  3. 剑指 Offer 59 - I. 滑动窗口的最大值
  4. cisco路由器基本命令配置
  5. 检测msmq里消息的数量
  6. JS Math对象中一些小技巧
  7. 播放RTMP协议的流媒体的几种选择
  8. 你写的前端到底用没用到这些
  9. 冲刺阶段——Day2
  10. fir.im Weekly - 给 Mac 应用开发者的教程
  11. 小程序 | 保存图片时处理名称的细节(时间戳+后缀名)
  12. C++——必须使用复制构造函数的情况
  13. [POI2010]Divine Divisor
  14. mongodb 3.4 安装_【云服务器Centos7.x建站】MongoDB 3.4安装、使用、错误总结
  15. php strom 快捷键,PHPStorm常用快捷键总结
  16. c语言stdio函数大全,初学者常用的stdio库,原来还有这么多知识点
  17. selenium的三种等待方式
  18. seo的日常工作内容
  19. 关于边缘计算和边云协同,看这一篇就够了~
  20. 4月5号-4月11号

热门文章

  1. IDEA切换分支 工作空间变化问题设置
  2. windows系统重装步骤
  3. 【网络基础知识】VLAN技术介绍(详细)
  4. 阿里云(飞天)里的 盘古
  5. 清华同方服务器硬盘更换,清华同方bios设置硬盘教程
  6. 叛乱2 linux服务器,叛乱沙漠风暴怎么开服?开服操作指南详解
  7. 最新版苹果开发者账号注册续费流程 Apple Developer
  8. BP反向传播算法原理及公式推导
  9. 5财务分析的基本方法-盈利能力分析
  10. 物联网(工程师)+嵌入式学习路线图各个阶段