Java使用动态规划算法思想解决背包问题

背包问题是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高

动态规划算法

动态规划算法的思想

动态规划算法处理的对象是多阶段复杂决策问题,动态规划算法和分治算法类似,其基本思想也是将待求解问题分解成若干个子问题(阶段),然后分别求解各个子问题(阶段),最后将子问题的解组合起来得到原问题的解,但是与分治算法不同的是,子问题往往不是相互独立的,而是相互联系又相互区别的

动态规划算法问题求解的目标是获取导致问题最优解的最优决策序列(最优策略)。对于一个决策序列,可以用一个数值函数(目标函数)衡量这个决策的优劣。

最优性原理

动态规划算法的最优性原理:一个最优决策序列具有这样的性质,不论初始状态和第一步决策如何,对前面的决策所形成的状态而言,其余的决策必须按照前一次决策所产生的新状态构成一个最优决策序列。

最优性原理体现为问题的最优子结构特性,对于一个问题,如果能从较小规模的子问题的最优解求得较大规模同类子问题的最优解,最终得到给定问题的最优解,也就是问题的最优解中所包含的子问题的最优解,这种性质被称为最优子结构性质。最优子结构特性使得在从较小问题的解构造较大问题的解时,只需考虑子问题的最优解,然后以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解,它保证了原问题的最优解可以通过求解子问题的最优解来获得,最优子结构的特性是动态规划算法求解问题的必要条件。

动态规划算法的三大特点

  • 如果求解的问题满足最优性原理,则说明用动态规划算法有可能解决该问题,在分析问题的最优子结构时,所使用的方法具有普遍性。要注意一个问题可以有多种方式刻画它的最优子结构,有些表示方法的求解速度更快(空间占用少,问题的维度低)。
  • 递归定义最优解决方案。动态规划的每一步决策都依赖于子问题的解,动态规划算法求解最优化问题的步骤为:找出最优解的结构,具体来说就是看这个问题是否满足最优子结构特性;其次递归定义一个最优解的值,即构造原问题和子问题之间的递归方程,原问题的最优解可以通过子问题的最优解获得。
  • 以自底向上的方式计算出最优解的值(最优解的目标函数的值)。对子问题的分解是基于原问题的分解的基础之上进行的,而且这些子问题的分解过程是相互独立的。在对原问题分解的过程中,会出现大量的共享重叠子问题,为了避免对大量重叠子问题的重复计算,一般动态规划算法从自底向上开始计算,对每一个问题只解一次,并且保存求解子问题的最优值,当再需要求解这个子问题的时候,可以用常数时间查看一下结果,而不是再递归的去求解每一个问题的解,因此提高了动态规划算法的效率。

动态规划算法中的0/1背包问题

0/1背包问题的规则是不允许该物品进行拆分,即只有把物品放入和不放入两个基本状态,要使用动态规划算法求解决如何放物品才可以是背包中的物品的总价值达到最高。

示例

有一个载重为10的背包,现有4类物品,每类物品的重量分别为(w0,w1,w2,w3)=(2,3,4,7),它们的价值分别为(p0,p1,p2,p3)=(1,3,5,9)。试问如何装载能够使背包容纳物品的价值最大。

package com.xuda.testimport java.util.Arrays;import java.util.Scanner;//m表示的是背包的容量,a表示有多少种类的物品,数组w用与存放每类物品的重量,数组val用于存放每类物品的价值public class my {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.print("请输入背包的容量:");int m = scanner.nextInt();Scanner inScanner = new Scanner(System.in);System.out.print("请输入物品的个数:");int a = inScanner.nextInt();int[] w = new int[a + 1];System.out.print("请输入物品的重量:" + " ");for (int i = 1; i <= a; i++) {w[i] = inScanner.nextInt();}int[] val = new int[a+ 1];System.out.print("请输入物品的价值:" + " ");for (int i = 1; i <= a; i++) {val[i] = inScanner.nextInt();}int n = val.length;int[][] path = new int[n +1][m+1 ];//创建二维数组//v[i][j]:表示在前i个物品中能够装入容量为j的背包中的最大价值int[][] v = new int[n +1][m + 1];//初始化第一行和第一列for (int i = 0; i < v.length; i++) {//v.length:获取二维数组的行数v[i][0] = 0;//将第一列设置为0}for (int i = 0; i < v[0].length; i++) {//v[0].length:获取二维数组的列数v[0][i] = 0;//将第一行设置为0}for (int i = 1; i < v.length; i++) {//int i = 1 不处理第一行for (int j = 1; j < v[0].length; j++) {//int j = 1 不处理第一列if (w[i - 1] > j) {v[i][j] = v[i - 1][j];} else {if (v[i - 1][j] < (val[i - 1] + v[i - 1][j - w[i - 1]])) {v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];//把当前情况记录到pathpath[i][j] = 1;} else {v[i][j] = v[i - 1][j];}}}}//输出二维数组:for (int[] ints : v) {System.out.println(Arrays.toString(ints));}//输出最后我们是放入的那些商品int i = path.length - 1;//行的最大下标int j = path[0].length - 1;//列的最大下标while (i > 0 && j > 0) {//从path的最后开始找if (path[i][j] == 1) {System.out.printf("第%d个商品放入背包\n", i-1);j -= w[i - 1];}i--;}}}
复制代码

输入一个背包容量为10,里面有4类物品,物品的重量分别为2,3,4,7,物品的价值分别为1,3,5,9

结果

动态规划算法的优点

若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

Java使用动态规划算法思想解决01背包问题相关推荐

  1. 动态规划算法思想解决找零钱问题

    前言 关于找零钱问题,网上已经有很多相关的资料以及优秀的文章博客等.这里写这篇博客的初衷很简单,就是为了方便自己,回过头来捡起这个知识能快一点,接受起来更易理解点:他人的文章写的再好,毕竟是别人的,学 ...

  2. 动态规划解决01背包问题

    转自:https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html 一.问题描述:有n 个物品,它们有各自的重量和价值,现有给定容量的背包 ...

  3. c语言 用回溯算法解决01背包问题,回溯法解决01背包问题

    <回溯法解决01背包问题>由会员分享,可在线阅读,更多相关<回溯法解决01背包问题(21页珍藏版)>请在人人文库网上搜索. 1.回溯法解决01背包问题,回溯法解决01背包问题, ...

  4. 0-1背包问题 动态规划java_C#使用动态规划解决0-1背包问题实例分析

    // 利用动态规划解决0-1背包问题 using System; using System.Collections.Generic; using System.Linq; using System.T ...

  5. 动态规划解决0-1背包问题详解(图文并茂)

    动态规划解决0-1背包问题 这个是网上比较好的案例,因为原文有些地方晦涩难懂,对于刚接触动态规划问题的朋友来说很不友好,所以很对地方加入了我自己的见解,也是作为我的一次学习历程. 一.问题描述: 有n ...

  6. Java通过递归解决0-1背包问题的代码

    下面的内容段是关于Java通过递归解决0-1背包问题的内容. public class Knapsack { public static void main(final String... args) ...

  7. 变邻域搜索算法解决0-1背包问题

    变邻域搜索算法解决0-1背包问题 本文是关于[数据魔术师]:干货 | 变邻域搜索算法解决0-1背包问题(Knapsack Problem)代码实例一文的个人学习笔记,改了一点原文中的代码,仅供个人参考 ...

  8. php 0-1,PHP 动态解决0-1背包问题

    这篇文章主要为大家详细介绍了PHP 动态解决0-1背包问题,具有一定的参考价值,可以用来参考一下. 对PHP动态规划解决0-1背包问题感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 背包 ...

  9. java数据结构-动态规划算法-一次性学会

    java数据结构-动态规划算法 算法介绍 最佳实践-背包问题 代码实践 寻找最长回文子串的求解 总结 算法介绍 动态规划算法的核心思想是:将大问题划分为小问题,一步步获取最优解 与分治算法类似,但也有 ...

最新文章

  1. 【设计模式】 模式PK:策略模式VS状态模式
  2. 解决上传文件或图片时选择相同文件无法触发change事件的问题
  3. 哈尔滨金融学院计算机系学生会,哈尔滨金融学院计算机系实习报告(毕业分散实习).doc...
  4. 90后售楼人员的肺腑之言:再便宜你也不能买的房子(转)
  5. element的滚动去掉横向_textarea去掉滚动条 textarea横向或纵向滚动条的去掉方法
  6. Cookie 和 Session的区别 1
  7. 开场 Live,分享点干货——「深入了解 Node.js 包与模块机制」
  8. CSS3中的动画示例
  9. 白宫任命退伍将军担任首位联邦首席信息安全官
  10. 一个简单限速器的java实现[2]
  11. oracle手注,oracle手注
  12. Android开发笔记(二十五)assets目录下的文件读取
  13. 反素数(高合成数?)
  14. 《应用商务统计分析》前言
  15. sdn交换机与普通交换机区别—Vecloud
  16. 内涵图:从明天起,做一个有内涵的人
  17. 计算机怎么转到超级用户,电脑系统管理员权限怎么设置为超级管理员权限
  18. 雨听 | 英语学习笔记(十五)~作文范文:私家车主应该为环境污染纳税吗?
  19. Python(函数与面向对象)
  20. 关于pytorch配置中遇到的问题1(YOLOV5)

热门文章

  1. 固然法院还没有正式出具逮捕令
  2. 台式机内存服务器内存性能,如何区别服务器内存与台式机内存?
  3. 8145v5 参数_参数估计
  4. MPR的线性组合性能
  5. ubuntu服务器创建用户并且分配磁盘空间
  6. python 网站开发环境_安吉公司网站建设:最好的Python开发环境
  7. 基于Beacon技术的智慧酒店解决方案
  8. Java多线程并行处理任务的实现
  9. 单声道数据转双声道_WAV格式播放时,如何双声道转为单声道。
  10. win10休眠开机后,屏幕卡顿问题解决