算法(Java实现)—— 动态规划算法
动态规划算法
应用场景—0-1背包问题
背包问题:有一个背包,容量为4磅,现有物品如下
| 物品 | 重量 | 价格 |
|---|---|---|
| 吉他(G) | 1 | 1500 |
| 音响(S) | 4 | 3000 |
| 电脑(L) | 3 | 2000 |
要求:
达到目标为装入的背包的总价值最大,且重量不超出
要求装入的物品不可重复
动态规划算法介绍
动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决,熊二一步步获取最优解的处理算法
与分治算法类似,但不同的是动态规划子问题不相互独立
动态规划可以通过填表的方式来逐步推进,得到最优解
解决0-1背包问题
主要思想
利用动态规划来解决,每次遍历到第i个物品,根据w[i]和v[i]来确定是否需要将该物品放入背包中。即对于给定的n个物品,令:
w[i]:第i个商品的重量
val[i]:第i个商品的价值
C:背包容量
v[i][j :表示前i个物品中能够装入容量为j的背包中的最大价值
则有下列结论:
v[i][0] = v[0][j] = 0;
当w[i] > j时:v[i][j] = v[i-1][j]
当j >= w[i]时:v[i][j] = max{v[i-1][j],v[i-1][j-w[i]] + val[i]}
思路图解
背包的填表过程
物品还未装入背包,初始状态
行,0磅,1磅……代表背包容量,哪一行表示可以放入此行及 以上行的物品,但是哪一行先方哪一行的物品
列,代表物品在对应背包容量下各自在背包中的价格
物品 0磅 1磅 2磅 3磅 4磅 0 0 0 0 0 吉他(G) 0 音响(S) 0 电脑(L) 0 加入现在只有吉他此时不论背包容量有多大,只能放一把吉他
物品 0磅 1磅 2磅 3磅 4磅 0 0 0 0 0 吉他(G) 0 1500(G) 1500(G) 1500(G) 1500(G) 音响(S) 0 电脑(L) 0 假如有吉他和音响,当背包容量同时满足多个物品时,考虑哪个物品价值更高将其放入
物品 0磅 1磅 2磅 3磅 4磅 0 0 0 0 0 吉他(G) 0 1500(G) 1500(G) 1500(G) 1500(G) 音响(S) 0 1500(G) 1500(G) 1500(G) 3000(S) 电脑(L) 0 假如由吉他,音响,电脑时,先放电脑,放完之后如果有空余空间可以放入其他物品则放入,否则不用再关心
物品 0磅 1磅 2磅 3磅 4磅 0 0 0 0 0 吉他(G) 0 1500(G) 1500(G) 1500(G) 1500(G) 音响(S) 0 1500(G) 1500(G) 1500(G) 3000(S) 电脑(L) 0 1500(G) 1500(G) 2000(L) 2000(L) + 1500(G) 则有下列结论:
//表示填入的表的第一行和第一列置0
v[i][0] = v[0][j] = 0;
//当新增加商品时,若新商品大于背包容量时,则直接使用上一单元格的装入策略
当w[i] > j时:v[i][j] = v[i-1][j]
//当新增加商品时,其容量小于背包容量,
//装入的策略:
//1. v[i-1][j]上一单元格的价值
//2. v[i-1][j-w[i]] + v[i]当前商品的 价值+剩余空间装入物品价值的最大 值
//3. 此时比较装入商品的价值,使用价值最 大的策略
当j >= w[i]时:v[i][j] = max{v[i-1][j],v[i-1][j-w[i]] + val[i]}
代码实现
package whyAlgorithm.dynamic;
import java.util.Arrays;
/**
* @Description TODO 动态规划解决0-1背包问题
* @Author why
* @Date 2020/12/9 21:04
* Version 1.0
**/
public class KnapsackProblem {
public static void main(String[] args) {
int[] w = {1,4,3};//物品重量
int[] val = {1500,2000,3000};//物品价值
int m = 4;//背包容量
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];
//初始化第一行和第一列,在本程序中可以不处理,因为默认为0
for (int i = 0; i < v.length; i++) {
//将第一列置为0
v[i][0] = 0;
//将第一行置为0
v[0][i] = 0;
}
//根据前面的公式动态规划处理
for (int i = 1; i < v.length; i++) {//不处理第一行
for (int j = 1; j < v[0].length; j++) {//不出来第一列
//公式
//因为i从1开始,故原公式修改为 w[i] = w[i-1]
if (w[i-1] > j){
v[i][j] = v[i-1][j];
}else {
//int b = v[i-1][j-w[i-1]] + val[i-1];
//int max = Math.max(v[i - 1][j], b);
//v[i][j] = max;
//为了记录商品存放到背包的情况不能简单地使用上面的公式,需要使用if,else体现这个公式
if (v[i-1][j] < v[i-1][j-w[i-1]] + val[i-1]){
v[i][j] = v[i-1][j-w[i-1]] + val[i-1];
//记录当前情况
path[i][j] = 1;
}else {
v[i][j] = v[i-1][j];
}
}
}
}
System.out.println("分配表:");
for (int i = 0; i < v[0].length-1; i++) {
System.out.println(Arrays.toString(v[i]));
}
//输出放入的哪些商品
//遍历path,这样输出会有误,我们要最后的放入
// for (int i = 0; i < path.length; i++) {
// for (int j = 0; j < path[0].length; j++) {
// if (path[i][j] == 1){
// System.out.printf("第%s个商品放入到背包\n",i);
// }
// }
// }
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("第%s个商品放入到背包\n",i);
j -= w[i-1];
}
i--;
}
}
}
算法(Java实现)—— 动态规划算法的更多相关文章
- 算法java实现--动态规划--电路布线问题
/* * dianlubuxian.java * Version 1.0.0 * Created on 2017年11月30日 * Copyright ReYo.Cn */ package reyo. ...
- JAVA分析html算法(JAVA网页蜘蛛算法)
近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...
- 排序算法-Java实现快速排序算法
- 算法 | Java 常见排序算法(纯代码)
目录 汇总 1. 冒泡排序 2. 选择排序 3. 插入排序 4. 快速排序 5. 归并排序 6. 希尔排序 6.1 希尔-冒泡排序(慢) 6.2 希尔-插入排序(快) 7. 堆排序 8. 计数排序 9 ...
- (java)五大常用算法
算法一:分治法 基本概念 1.把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题--直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并. 2.分治策略是对于一个 ...
- 快速排序算法 java 实现
快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...
- ID3算法Java实现
ID3算法java实现 1 ID3算法概述 1.1 信息熵 熵是无序性(或不确定性)的度量指标.假如事件A的全概率划分是(A1,A2,...,An),每部分发生的概率是(p1,p2,...,pn).那 ...
- Java数据结构和算法(五)--希尔排序和快速排序
在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...
- Java数据结构和算法(一)--栈
栈: 英文名stack,特点是只允许访问最后插入的那个元素,也就是LIFO(后进先出) jdk中的stack源码: public class Stack<E> extends Vector ...
- Java数据结构和算法(六)--二叉树
什么是树? 上面图例就是一个树,用圆代表节点,连接圆的直线代表边.树的顶端总有一个节点,通过它连接第二层的节点,然后第二层连向更下一层的节点,以此递推 ,所以树的顶端小,底部大.和现实中的树是相反的, ...
随机推荐
- FL Studio中的文件设置介绍
在fl中,我们想要找到文件设置选项,可以在主菜单中选择选项-文件设置来打开,也可以通过按"F10"快捷键来一步打开." 文件设置"页面可以将其他文件夹链接到浏览 ...
- CorelDRAW文件损坏的几种解决方法
以前做好的CorelDRAW文件突然打不开了,或者是死机.非法操作等原因造成CorelDRAW文件损坏,有时打开源文件发现一片空白,源文件保存损坏无法打开怎么办?此时不要着急,你可以试试以下几种办法帮 ...
- C语言讲义——库函数排序qsort
qsort函数在在stdlib.h中. 函数原型 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void ...
- 蓝桥杯——快速排序(2018JavaB组第5题9分)
快速排序(18JavaB5,9') 以下代码可以从数组a[]中找出第k小的元素. 它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的. 请仔细阅读分析源码,填写划线部分缺失的内容. impo ...
- DataTable 将一列转为List
c# linq用起来特方便,因此我们习惯性的用list来操作. 这里我们将 DataTable 一列转为List: List<T> homeworkIdList = (from r in ...
- 数据库原理-事务隔离与多版本并发控制(MVCC)
刚来美团实习,正好是星期天,不得不说,其内部的资料很丰富,看了部分文档后,对数据库事务这块更理解了.数据库事务的ACID,大家都知道,为了维护这些性质,主要是隔离性和一致性,一般使用加锁这种方式.同时 ...
- Python音视频开发:消除抖音短视频Logo的图形化工具实现
☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...
- 第7.3节 Python特色的面向对象设计:协议、多态及鸭子类型
Python是一种多态语言,其表现特征是:对象方法的调用方只管方法是否可调用,不管对象是什么类型,从而屏蔽不同类型对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化. 一. P ...
- 第4.6节 print、import及断言
一.print函数 前面第二章介绍了print的语法,其语法如下: print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ...
- 第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样?
第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样? 一. 案例说明 我们上节提到了,使用property函数定义的属性不要与类内已经定义的普通实例变量重 ...