Unit2_1:动态规划DP

2023-11-07 12:20
文章标签 动态 规划 dp unit2

本文主要是介绍Unit2_1:动态规划DP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、介绍
  • 二、0-1背包问题
    • 问题描述
    • 分析
    • 伪代码
    • 时间复杂度
  • 三、钢条切割问题
    • 问题描述
    • 分析
    • 伪代码
    • 过程
  • 四、矩阵链乘法
    • 背景
    • 性质
    • 分析
    • 案例
    • 伪代码

一、介绍

动态规划类似于分治法,它们都将一个问题划分为更小的子问题
最优子结构:问题的最优解包含子问题的最优解。DP适用的原因就在这
当子问题重叠时,即它们共享公共子问题时,可减小时间复杂度
DP通常用于优化问题,有许多解决方案的问题,我们想找到最好的一个
DP问题的求解思路一般就是
   先描述最优解的结构
   递归地定义最优解的值
   计算最优解的值(通常是自下而上)
   根据计算出的信息构造最优解(如果需要)

二、0-1背包问题

问题描述

n 个商品 , v i 表示第 i 个物品的价值 , w i 表示第 i 个物品的重量 一个能装入 W 重的背包 , 使用背包装下价值最多的物品 限制条件 : 我们不能取物品的一部分,我们取整个物品,或者什么都不取。 ( 这就是为什么它被称为 0 − 1 背包。 ) n个商品,v_i表示第i个物品的价值,w_i表示第i个物品的重量\\ 一个能装入W重的背包,使用背包装下价值最多的物品\\ 限制条件:我们不能取物品的一部分,我们取整个物品,或者什么都不取。\\(这就是为什么它被称为0-1背包。) n个商品,vi表示第i个物品的价值,wi表示第i个物品的重量一个能装入W重的背包,使用背包装下价值最多的物品限制条件:我们不能取物品的一部分,我们取整个物品,或者什么都不取。(这就是为什么它被称为01背包。)

分析

V [ i , w ] 表示重量为 w 背包 , 在前 i 种商品选择的最大价值 V[i,w]表示重量为w背包,在前i种商品选择的最大价值 V[i,w]表示重量为w背包,在前i种商品选择的最大价值
对于第i个物品,我们要么选取它,要么不选择,因此最大价值转移方程为

V [ i , w ] = m a x ( V [ i − 1 , w ] , v i + V [ i − 1 , w − w i ] ) V[i,w]=max(V[i-1,w],v_i+V[i-1,w-w_i]) V[i,w]=max(V[i1,w],vi+V[i1,wwi])

若使用递归重复计算很多值,时间复杂度为 T ( n ) = O ( 2 W ) T(n)=O(2^W) T(n)=O(2W),因此要重复利用最优子结构的性质.
在这里插入图片描述
初始化: V [ 0 , w ] = 0 V[0,w]=0 V[0,w]=0 f o r for for 0 ≤ w ≤ W 0 \leq w \leq W 0wW 此时没有商品,自然没有价值
接下来按顺序填表:
在这里插入图片描述
在这里插入图片描述

伪代码

Knapsack(v,w,n,W)
for w=0 to W doV[0,w]=0;
end
for i=1 to n dofor w=0 to Wif w[i]<W thenV[i,w] = max{V[i-1,w],v[i]+V[i-1,w-w[i]]}elseV[i,w] = V[i-1,w]endend
end
return V[n,W]

若是想要记录最优解的路径,需要维护一个 k e e p [ i ] [ w ] keep[i][w] keep[i][w],如果选择i作为 V [ i , w ] V[i,w] V[i,w],则 k e e p [ i ] [ w ] = 1 keep[i][w]=1 keep[i][w]=1
路径只需要
i f k e e p [ n , w ] = 1. 则选择 n 且继续从 k e p p [ n − 1 ] [ w − w n ] 开始 if keep[n,w]=1.则选择n且继续从kepp[n-1][w-w_n]开始 ifkeep[n,w]=1.则选择n且继续从kepp[n1][wwn]开始
i f k e e p [ n , w ] = 0. 则不选择 n 且继续从 k e p p [ n − 1 ] [ w ] 开始 if keep[n,w]=0.则不选择n且继续从kepp[n-1][w]开始 ifkeep[n,w]=0.则不选择n且继续从kepp[n1][w]开始
因此路径输出代码:

K ← W
for i ← n to 1 doif keep[i][K] is equal to 1 thenOutput iK ← K-w[i]end
end

在这里插入图片描述

时间复杂度

两层循环,时间复杂度 T ( n ) = O ( n W ) T(n)=O(nW) T(n)=O(nW)
本质上,DP问题是用空间换时间,将结果放在空间中而不用下次花费时间再去计算

三、钢条切割问题

问题描述

给定一个长度为 n 的棒材和一个价格表,其中 p i 为长度为 i 的棒材的价格 确定最大的收入 r n , 以及切割钢条的方案 给定一个长度为n的棒材和一个价格表,其中pi为长度为i的棒材的价格\\ 确定最大的收入r_n,以及切割钢条的方案 给定一个长度为n的棒材和一个价格表,其中pi为长度为i的棒材的价格确定最大的收入rn,以及切割钢条的方案

分析

此题暴力解法,即遍历长度.每个点有两种选择,切 o r or or不切,判断哪种选择最合适即可,时间复杂度 T ( n ) = O ( 2 n ) T(n)=O(2^n) T(n)=O(2n).
考虑到最优子结构,可利用较短的杆最优收益来确定较长的,此题的状态转移如下:
r n = m a x ( p n , r 1 + r n − 1 , r 2 + r n − 2 , . . . . . , r n − 1 + r 1 ) r_n=max(p_n,r_1+r_{n-1},r_2+r_{n-2},.....,r_{n-1}+r_1) rn=max(pn,r1+rn1,r2+rn2,.....,rn1+r1)
简化定义:
r n = m a x ( p i + r n − i ) r_n=max(p_i+r_{n-i}) rn=max(pi+rni)      1 ≤ i ≤ n 1 \leq i \leq n 1in

伪代码

r[0] ← 0
for j ← 0 to n doq  ← -∞for i  ← 1 to j doq  ← max(q,p[i]+r[j-i])endr[j]  ← q if j != 0
end
return r[n]

这种做法时间复杂度 T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)
若是需要保存切割的方案,则需要维护一个 s [ n ] s[n] s[n]数组. s [ n ] 保存前一次切割的长度 s[n]保存前一次切割的长度 s[n]保存前一次切割的长度:

r[0] ← 0
for j ← 0 to n doq  ← -∞for i  ← 1 to j doif q < p[i]+r[j-i] thenq ← p[i]+r[j-i]s[j] ← iendendr[j]  ← q if j != 0
end
while n>0 doOutput s[n]n ← n-s[n]
end

过程

在这里插入图片描述

四、矩阵链乘法

背景

p × q 矩阵 a 和 q × r 矩阵 B 的乘积 C = A B 是 p × r 矩阵 p × q矩阵a和q × r矩阵B的乘积C = AB是p × r矩阵 p×q矩阵aq×r矩阵B的乘积C=ABp×r矩阵

c [ i ] [ j ] = ∑ k = 1 q a [ i ] [ k ] b [ k ] [ j ] c[i][j]=\sum_{k=1}^{q}a[i][k]b[k][j] c[i][j]=k=1qa[i][k]b[k][j] f o r for for 1 ≤ i ≤ p 1 \leq i \leq p 1ip a n d and and 1 ≤ j ≤ r 1 \leq j \leq r 1jr
时间复杂度:注意 C C C p r pr pr个条目,每个条目需要 O ( q ) O(q) O(q)时间来计算,所以整个过程需要 O ( p q r ) O(pqr) O(pqr)时间

性质

矩阵乘法有结合律, A 1 A 2 A 3 = ( A 1 A 2 ) A 3 = A 1 ( A 2 A 3 ) A_1A_2A_3=(A_1A_2)A_3=A_1(A_2A_3) A1A2A3=(A1A2)A3=A1(A2A3)
因此当计算 A B C ABC ABC时,有两种选择, ( A B ) C = A ( B C ) (AB)C=A(BC) (AB)C=A(BC)
m u l t [ ( A B ) C ] = p q r + p r s mult[(AB)C]=pqr+prs mult[(AB)C]=pqr+prs
m u l t [ A ( B C ) ] = q r s + p q s mult[A(BC)]=qrs+pqs mult[A(BC)]=qrs+pqs
每种选择的时间复杂度不一样
因此矩阵链乘法需要解决的就是怎么样结合能使得计算的量最小

分析

令 A i . . j = A i A i + 1 . . . A j 令A_{i..j}=A_iA_{i+1}...A{j} Ai..j=AiAi+1...Aj,显然, A i . . j A_{i..j} Ai..j P i − 1 × P j P_{i-1}×P_j Pi1×Pj的矩阵
A i . . j A_{i..j} Ai..j可以表示为 A i . . j = ( A i . . . A k ) ( A k + 1 . . . A j ) = A i . . k A k + 1.. j A_{i..j}=(A_i...A_k)(A_{k+1}...A{j})=A_{i..k}A_{k+1..j} Ai..j=(Ai...Ak)(Ak+1...Aj)=Ai..kAk+1..j

1 ≤ i ≤ j ≤ n 1 \leq i \leq j \leq n 1ijn时,令 m [ i , j ] m[i,j] m[i,j]表示计算 A i . . j A_{i..j} Ai..j所需的最小乘法次数。最优成本可以用下面的递归定义来描述

m ( i , j ) = { 0 i f i = j m i n i ≤ k ≤ j ( m ( i , k ) + m ( k + 1 , j ) + p i − 1 p k p j ) i f n = 1 m(i,j)=\left\{ \begin{array}{ll} 0 & if \space i=j \\ min_{i \leq k \leq j} (m(i,k)+m(k+1,j)+p_{i-1}p_kp_j)& if \space n=1 \nonumber \end{array} \right. m(i,j)={0minikj(m(i,k)+m(k+1,j)+pi1pkpj)if i=jif n=1

注意计算并保存 m [ i , j ] m[i, j] m[i,j]的顺序是,当计算 m [ i , j ] m[i, j] m[i,j]时, m [ i , k ] m[i, k] m[i,k] m [ k + 1 , j ] m[k + 1, j] m[k+1,j]的值已经可用,因此按矩阵链长度的递增顺序计算它们:

m [ 1 , 2 ] , m [ 2 , 3 ] , m [ 3 , 4 ] , … , m [ n − 3 , n − 2 ] , m [ n − 2 , n − 1 ] , m [ n − 1 , n ] m[1,2], m[2,3], m[3,4],…, m[n-3,n-2], m[n-2,n-1], m[n-1,n] m[1,2],m[2,3],m[3,4],,m[n3,n2],m[n2,n1],m[n1,n]
m [ 1 , 3 ] , m [ 2 , 4 ] , m [ 3 , 5 ] , … , m [ n − 3 , n − 1 ] , m [ n − 2 , n ] m[1,3], m[2,4], m[3,5],…, m[n-3,n-1], m[n-2,n] m[1,3],m[2,4],m[3,5],,m[n3,n1],m[n2,n]
m [ 1 , 4 ] , m [ 2 , 5 ] , m [ 3 , 6 ] , … , m [ n − 3 , n ] m[1,4], m[2,5], m[3,6],…, m[n-3,n] m[1,4],m[2,5],m[3,6],,m[n3,n]
… …
m [ 1 , n − 1 ] , m [ 2 , n ] m[1,n-1], m[2,n] m[1,n1],m[2,n]
m [ 1 , n ] m[1,n] m[1,n]

若需要记录分隔括号路径,需要维护一个二维数组 s [ 1.. n , 1.. n ] s[1..n, 1..n] s[1..n,1..n],里面存储 A i . . j A_{i..j} Ai..j的最优分隔k
s [ 1 , n ] s[1,n] s[1,n]           ( A 1 . . A s [ 1 , n ] ) ( A s [ 1 , n ] + 1 . . . A n ) (A_1..A_{s[1,n]})(A_{s[1,n]+1}...A{n}) (A1..As[1,n])(As[1,n]+1...An)
s [ 1 , s [ 1. n ] ] s[1,s[1.n]] s[1,s[1.n]]           ( A 1 . . A s [ 1 , s [ 1. n ] ] ) ( A s [ 1 , s [ 1. n ] ] + 1 . . . A n ) (A_1..A_{s[1,s[1.n]]})(A_{s[1,s[1.n]]+1}...A{n}) (A1..As[1,s[1.n]])(As[1,s[1.n]]+1...An)

案例

在这里插入图片描述

伪代码

MatrixChain(p,n)
for i ← 1 to n dom[i,i] ← 0;
end
for l ← 2 to n dofor i ← 1 to n-l+1 doj ← i+l-1;m[i,j] ← ∞for k ← i to j-1 doq ← m[i,k]+m[k+1,j]+p[i-1]*p[k]*p[j]if q<m[i,j] thenm[i,j] ← qs[i,j] ← kendendend
end
return m[1,n] and s

三层循环,时间复杂度 T ( n ) = O ( n 3 ) T(n)=O(n^3) T(n)=O(n3)

这篇关于Unit2_1:动态规划DP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/363546

相关文章

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

基于Canvas的Html5多时区动态时钟实战代码

《基于Canvas的Html5多时区动态时钟实战代码》:本文主要介绍了如何使用Canvas在HTML5上实现一个多时区动态时钟的web展示,通过Canvas的API,可以绘制出6个不同城市的时钟,并且这些时钟可以动态转动,每个时钟上都会标注出对应的24小时制时间,详细内容请阅读本文,希望能对你有所帮助...

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配