常用十大算法_动态规划算法(DP)

article/2025/9/13 8:59:11

动态规划算法(DP)

高能预警:DP算法不容易理解,需要动脑筋+查资料+找例题

动态规划算法(Dynamic Programming),是将复杂问题拆分成子问题,并在子问题的基础上,求解复杂问题,子问题之间不是独立的,而是相互依存的。

动态规划算法有两种实现形式:递归,非递归

有点莫名其妙对吧,下面以例子来了解(递归的容易,非递归的难,要有心理准备:<)

【例一】01背包问题:有个容量为4的背包,有以下3种物品,物品具有价值和重量属性,要求装入的物品价值总和最大且装入物品不能重复

解法1,递归实现动态规划算法

算法分析:

约定 weight[] 装载物品的重量,value[] 装载物品的价值。为了方便人机交互,定义上两个数字第一个元素为0。

装与不装,无非是受背包容量,和价格最大化限制。

我们假设 OPT(n,i) 代表对第n个物品操作且容量为i时的最优解(价值最大)。那么对于第n个物品而言,受背包容量限制:

当容量够的时候,我们有两种对n物品的操作,选n,不选n,选n时其对应最优解为 value[n]+OPT(n-1,i-weight[i]),不选n时其对应最优解为 OPT(n-1,i)。而此时 OPT(n,i)=MAX{value[n]+OPT(n-1,i-weight[i]),OPT(n-1,i)}

当容量不够时,我们只有一种对n物品的操作,即不选n。此时OPT(n,i)=OPT(n-1,i)

以上的运算流程是基于递归完成的。所以要设置递归结束条件:当n==0时,说明没有物品了,return 0;

根据以上推理得到该问题的状态转移方程(别被式子吓到了,这是纸老虎)

代码实现:

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.dynamicProgramming;public class 动态规划算法_DP_01背包问题 {static int[] value={0,1500,3000,2000};//分别对应物品a,b,c,为了方便人机交互,定义第0个物品为0static int[] weight={0,1,4,3};//分别对应物品a,b,c,为了方便人机交互,定义第0个物品为0static int bag=4;//背包容量public static void main(String[] args) {System.out.println(re_OPT(3,4));}/*** 动态规划:递归来求最优解* @param n 第n个物品* @param bag 背包容量* @return 最优解*/public static int re_OPT(int n, int bag){if (n==0){return 0;}if (bag>=weight[n]){return Math.max(value[n]+ re_OPT(n-1,bag-weight[n]), re_OPT(n-1,bag));}else {return re_OPT(n-1,bag);}}}
3500

递归式实现了,仍然存在有个小问题。

 递归的本身设计,就包含了大量的重复计算,如上图,相同颜色的方框,表示重复运算。这在海量数据计算过程中,由于递归将创建大量的栈空间,进行重复运算。极易引发栈溢出。为了解决这一问题,需要彻底改变运算模式-------非递归动态规划

 

解法2,非递归实现动态规划算法

算法分析:

将题目中的信息全部整合到一个二维表中,该表对应了容量从4到0的各种情况下的最优解。

表的第一行,由于价值为0,所以全是0。表的第一列,由于容量为0,所以全是0。

其他的情况,需要通过程序进行求解。每一个空都对应一种情况,每种情况都受容量限制,每种情况都有两种操作(选与不选)。

与解法1不同的是,这里是自底而上求解(表中从左至右,从上至下)。将每次计算的结果保存在二维数组中,求解的下一个结果依赖于上一次已经求好的结果。这就解决了递归式重复计算的问题。

最终的答案,就在二维数组的右下角。

代码实现:

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.dynamicProgramming;public class 动态规划算法_DP_01背包问题 {static int[] value={0,1500,3000,2000};//分别对应物品a,b,c,为了方便人机交互,定义第0个物品为0static int[] weight={0,1,4,3};//分别对应物品a,b,c,为了方便人机交互,定义第0个物品为0static int bag=4;//背包容量public static void main(String[] args) {System.out.println(dp_OPT(3,4));}/*** 动态规划:非递归求最优解* @param n 第n个物品* @param bag 背包容量* @return 最优解*/public static int dp_OPT(int n, int bag){int[][] result=new int[weight.length][bag+1];//创造一个二维数组,用来存放各种情况对应的最优解,前[]保存第几个物品,后面[]保存多少背包容量//将第一行与第一列重置为0for (int i=0;i<result[0].length;i++){result[0][i]=0;}for (int j=0;j<result.length;j++){result[j][0]=0;}for (int i=1;i<result.length;i++){for (int j=1;j<result[0].length;j++){result[i][j] = j>=weight[i]?Math.max(value[i]+result[i-1][j-weight[i]],result[i-1][j]):result[i-1][j];}}return result[n][bag];}}
3500

 

【例二】 求相隔数据和最大值:有数据 {5,7,3,1,4,2} 需要间隔式的取出几个数使数之和最大,求出最大值。

代码实现:

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.dynamicProgramming;public class 动态规划算法_DP_相隔数据和最大 {public static void main(String[] args) {int[] data=new int[]{5,7,3,1,4,2};System.out.println(re_OPT(data,5));System.out.println(dp_OPT(data,5));}/*** 动态规划:递归式计算出最优解* @param data 需要求解的数据* @param i 在第i个数据前进行最优解计算* @return 返回最优解*/public static int re_OPT(int[] data, int i){if (i==0){//i==0时,第一个数据本身就是最优解。递归终止条件return data[0];}else if (i==1){//i==1是,前两个数中的最大值就是最优解。递归终止条件return Math.max(data[0],data[1]);}else {int A= re_OPT(data,i-2)+data[i];//A方案:选当前数据int B= re_OPT(data,i-1);//B方案:不选当前数据return Math.max(A,B);//在AB方案中,返回最大值作为最优解}}/*** 动态规划:非递归计算出最优解* @param data 需要求解的数据* @param i 在第i个数据前进行最优解计算* @return 返回最优解*/public static int dp_OPT(int[] data, int i){int[] opt=new int[data.length];int A;int B;opt[0]=data[0];opt[1]=Math.max(data[0],data[1]);for (int j=2;j<data.length;j++){A=opt[j-2]+data[j];//A方案:选当前数据B=opt[j-1];//B方案:不选当前数据opt[j]=Math.max(A,B);}return opt[i];}
}
12
12

 

【例三】数据求和匹配:{3,34,4,12,5,2}的数据中,给出一个待匹配的值n,问是否能从数据中任意取出几个数,使得之和等于n ?

代码实现:

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.dynamicProgramming;public class 动态规划算法_DP_数据求和匹配 {static int[] data={3,34,4,12,5,2};public static void main(String[] args) {System.out.println(re_OPT(data.length-1,9));System.out.println(re_OPT(data.length-1,13));System.out.println(dp_OPT(data.length-1,9));}/*** 动态规划:递归求出在一组数据中,是否有相加之和为待匹配数的情况* @param i 数组索引* @param a 待匹配数* @return true or false*/public static boolean re_OPT(int i, int a){if (a==0){//终止递归return true;}else if (i==0){//终止递归return data[i]==a;}else if (data[i]>a){//剪枝return re_OPT(i-1,a);}return re_OPT(i-1,a-data[i])|| re_OPT(i-1,a);//两种方案,选与不选}/*** 动态规划:非递归出在一组数据中,是否有相加之和为待匹配数的情况* @param i 数组索引* @param a 待匹配数* @return true or false*/public static boolean dp_OPT(int i, int a){boolean[][] res=new boolean[data.length][a+1];boolean A,B;for (int x=0;x<res.length;x++){for (int y=0;y<a+1;y++){if (y==0){res[x][y]=true;}if (x==0 && y==data[0]){res[x][y]=true;}}}for (int x=1;x<res.length;x++){for (int y=1;y<a+1;y++){if (data[x]>y){res[x][y]=res[x-1][y];}else {A=res[x-1][y-data[x]];B=res[x-1][y];res[x][y]=A||B;}}}return res[i][a];}
}
true
false
true

 

【例四】最优收益问题:如下图,8个任务分布在0~11的时间段内,每个任务对应的收益不同,(1号任务,收益5),在一个时间段内只能做一件任务。问在8个任务中最优收益为多少?

代码实现: 

package cn.dataStructureAndAlgorithm.demo.tenAlgorithm.dynamicProgramming;
public class 动态规划算法_DP_最优收益问题 {static int[][] taskTime={{0,0},{1,4},{3,5},{0,6},{4,7},{3,8},{5,9},{6,10},{8,11}};//存储任务时长static int[] income={0,5,1,8,4,6,3,2,4};//存储任务收益public static void main(String[] args) {System.out.println(OPT(8));}/*** 动态规划:递归计算出最优解* @param i 开始计算的任务序号* @return 最优解*/public static int OPT(int i){if (i==0){//当i为1时,说明已经完成规划内的任务,停止递归return 0;}int A=income[i]+OPT(prev(i));//方案1:选择当前任务int B=OPT(i-1);//方案2:不选择当前任务return Math.max(A,B);//求最优解}/*** 根据任务时长获取当前任务之前的最近可用任务* @param i 当前任务* @return 最近可用任务*/public static int prev(int i){int value=taskTime[i][0];while (true){if (i==1){return 0;}if (value>=taskTime[i-1][1]){return i-1;}i--;}}
}
13

推荐关于动态规划算法的博文

教你彻底学会动态规划——入门篇

 


其他常用算法,见下各链接

【常用十大算法_二分查找算法】

【常用十大算法_分治算法】

【常用十大算法_贪心算法】

【常用十大算法_KMP算法】

【常用十大算法_普里姆(prim)算法,克鲁斯卡尔(Kruskal)算法】

【常用十大算法_迪杰斯特拉(Dijkstra)算法,弗洛伊德(Floyd)算法】

【常用十大算法_回溯算法】

 

【数据结构与算法整理总结目录 :>】<-- 宝藏在此(doge)  

 


http://chatgpt.dhexx.cn/article/tvHSRf6g.shtml

相关文章

动态规划算法(DP)

校招笔试面试前,大家一般都会先去牛客网上刷刷题,《剑指offer》,《leetcode》走起来,然后初次入手,发现很多不会,不会到什么程度呢,连个想法都没有,于是就去讨论区看答案,然后java大神,c++大神会给出花式解答,他们喜欢在答案前加一句,简单的dp算法,递归就可以解决…

【算法笔记】树形DP算法总结详解

0. 定义 树形DP&#xff0c;又称树状DP&#xff0c;即在树上进行的DP&#xff0c;是DP&#xff08;动态规划&#xff09;算法中较为复杂的一种。 1. 基础 令 f [ u ] f[u]~ f[u] 与树上顶点 u u u有关的某些数据&#xff0c;并按照拓扑序&#xff08;从叶子节点向上到根节点…

★动态规划(DP算法)详解

什么是动态规划&#xff1a;动态规划_百度百科 内容太多了不作介绍&#xff0c;重点部分是无后效性&#xff0c;重叠子问题&#xff0c;最优子结构。 问S->P1和S->P2有多少种路径数&#xff0c;毫无疑问可以先从S开始深搜两次&#xff0c;S->P1和S->P2找出所有路…

ubuntu安装qt

Ubuntu安装qt 到qt官网下载“qt-opensource-linux-x64-5.9.1.run” 分别安装g, build-essential, libglq-mesa-dev, libglu1-mesa-dev freeglut3-dev 输入指令&#xff1a;”sudo apt-get install g” -> “sudo apt-get install build-essential” -> “sudo apt-get i…

QT安装、构建套件(MSVC、MinGW)配置

QT安装、构建套件(MSVC、MinGW)配置 1. QT框架及QT Creator下载 登录QT官网-https://www.qt.io/download。 点击downloads for open source users 在页面最下方&#xff0c;点击Download the QT online Installer。 在安装网页的最下方处有一行小字 “We do recommend yo…

QT linux安装

转载地址&#xff1a;http://www.cnblogs.com/tangkaixuan/p/6504102.html 文章来自https://lug.ustc.edu.cn/sites/qtguide/ 1.4 Qt在Linux下安装 Qt在Linux系统里的安装要稍微复杂一些&#xff0c;因为Linux发行版众多&#xff0c;所以安装过程有些差异。 由于Linux系统都可…

Qt国内镜像安装

下载安装程序 https://download.qt.io/official_releases/online_installers/ 使用国内镜像打开安装程序 G:\下载\qt-unified-windows-x64-4.5.1-online.exe --mirror https://mirror.nju.edu.cn/qt清华源 https://mirrors.tuna.tsinghua.edu.cn/qt/online/qtsdkrepository/win…

Qt下载与安装

一、Qt和Qt Creator的区别 Qt是C的一个库&#xff0c;或者说是开发框架&#xff0c;里面集成了一些库函数&#xff0c;提高开发效率。 Qt Creator是一个IDE&#xff0c;就是一个平台&#xff0c;一个开发环境&#xff0c;类似的比如说VS&#xff0c;也可以进行Qt开发&#xff…

Ubuntu 安装QT

一、最近这家公司接到一个订单&#xff0c;客户使用到国产操作系统&#xff0c;意味着需要使用到 Linux 系统&#xff0c;于是乎&#xff0c;之前的东西又要捡起来&#xff0c;而且&#xff0c;平时代码主要是windows 平台&#xff0c;这次需要将代码移植到linux 平台&#xff…

QT的安装------QT

由于现在的qt都是线上下载了&#xff0c;那我们就去qt的官网下载 download.qt.io 我们选择倒数第二个------archive(档案)&#xff0c;顺便学一下英文。 然后选择online install&#xff08;在线安装&#xff09; 身为先进人&#xff0c;当然选择最新的版本&#xff08;团新版…

VS+QT安装配置

心血来潮&#xff0c;装个QT&#xff0c;遇到好多问题&#xff0c;记录一下&#xff08;铭记那些踩过的坑&#xff09; 软件版本&#xff1a;vs是2022&#xff0c;qt是6.3.1 qt下载地址&#xff1a;Download Qt | Develop Desktop & Embedded Systems | Qt 点进去往下翻&…

Windows Qt安装教程

目录 一、Qt安装包下载二、Qt安装流程 一、Qt安装包下载 Qt官网&#xff1a;https://download.qt.io/ Qt官方提供的专门的资源下载网站&#xff0c;所有的开发环境和相关工具都可以从这里下载&#xff0c;Qt 官方下载网站如下图&#xff1a; 点击进入archive目录&#xff0c;…

Qt安装教程-详细

本文主要介绍了Qt5.9.7的安装步骤。 Qt下载 Qt的下载地址: http://download.qt.io/archive/qt/ qt-opensource-windows-x86-5.9.7.exe 是一个综合的安装包(5.8之前分开下载各个编译器版本SDK)&#xff0c;下载后安装的时候可以选择安装哪个编译器对应的SDK。一般可选MinGW 或…

QT下载安装

1、下载路径 https://download.qt.io/archive/qt/5.9/5.9.9/ 文件比较大&#xff0c;建议可以Qt 镜像网站 下载 国内著名的 Qt 镜像网站&#xff0c;主要是各个高校的&#xff1a;中国科学技术大学&#xff1a;http://mirrors.ustc.edu.cn/qtproject/ 清华大学&#xff1a;htt…

QT安装 and VS2019中安装QT插件

目录 VS中安装QT扩展插件1. 安装qt软件2. 在VS中安装qt扩展插件 VS中创建QT项目 VS中安装QT扩展插件 1. 安装qt软件 QT下载网址&#xff08;各版本&#xff09;. QT(5.12.11)直达界面. 根据操作系统不同&#xff0c;选择相应版本下载 双击运行… 输入QT账号信息&#xff0…

QT安装简介

1、下载QT安装包 下载网址&#xff1a;http://download.qt.io/ 或者http://download.qt.io/archive/qt/ 选择一个你需要的版本&#xff0c;例如 5.10 点击进去后&#xff0c;选择对应操作系统的安装包下载&#xff0c;例如qt-opensource-windows-x86-5.10.0.exe 2、安装QT …

QT安装教程(简易)

官方网址 Qt官方网址&#xff1a;http://download.qt.io 注意&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;这里下载记得要下载5版本以上的&#xff0c;因为5版本以上的自带打包工具&#xf…

Qt的安装及配置

一、Qt的安装 1.下载链接 或者 网盘下载 链接: https://pan.baidu.com/s/15Fwh8kOtrj4GIIg6ptnb7A 提取码: uvar 2.先注册账号&#xff0c;用自己的qq邮箱就可(注意&#xff1a;密码要有数字和大小写字母) 3.看图 4. 第一个&#xff1a;通过在Q中启用发送假名使用统计数据来…

Linux下的QT安装及初步使用过程(一)

目录 1.QT的安装 2.创建第一个QT程序 &#xff08;1&#xff09;QT代码&#xff08;C&#xff09; &#xff08;2&#xff09;使用qmake工具生成工程文件 ①确保qmake是可用的 ②如果不能找到qmake&#xff0c;则以下方式参考 ③使用qmake生成工程文件 ④生成Makefile文…

QT的安装 [新版2022]

QT的安装 [新版2022] 1 概述2 qt官网3 下载安装3.1 登录账号3.2 阅读同意许可3.3 开始安装3.4 帮助改进建议3.5 指定安装目录3.6 选择组件3.7 选择版本的依赖文件3.8 手动下载安装程序 1 概述 最近QT发布了6版本&#xff0c;5.x版本依然坚挺&#xff0c;官方也给出了LTS的标识…