【算法】动态规划(第五章习题解答)

news2024/12/24 11:36:18

5 动态规划

在这里插入图片描述

5.1

图书馆大门前有 n n n 级台阶, 你每次跨上 1 1 1 级或者 2 2 2 级, 请问等上 n n n 级台阶总共有多少种不同的方法? 设计一个算法求解上述问题, 尝试写出公式, 说明算法设计思想和时间复杂度.

算法设计:核心思路是函数的递归调用,当处理 n n n级台阶时,如果跨上1级则还需要处理 n − 1 n-1 n1级台阶,如果跨上 2 2 2级则还需要处理 n − 2 n-2 n2级台阶,容易得到递推表达式 f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n)=f(n-1)+f(n-2) f(n)=f(n1)+f(n2),这里要注意递归终止条件的设定,为了避免多统计要在 n < 0 n<0 n<0时返回 0 0 0,而在 n = 0 n=0 n=0时返回 1 1 1,代表 1 1 1种走法。

数据输入:台阶级数 n n n

结果输出:走台阶的不同方法数 s o l v e N u m b e r solveNumber solveNumber

伪码描述:

f i n d s o l v e N u m b e r   ( n ) : findsolveNumber\ (n): findsolveNumber (n):

  1. i f    n < 0 if\ \ n<0 if  n<0
  2. $then \ return\ 0 $
  3. i f    n = 0 if\ \ n=0 if  n=0
  4. $then \ return\ 1 $
  5. r e t u r n   f i n d s o l v e N u m b e r ( n − 1 ) + f i n d s o l v e N u m b e r ( n − 2 ) return \ findsolveNumber(n-1)+findsolveNumber(n-2) return findsolveNumber(n1)+findsolveNumber(n2)

递归方程:
{ W ( n ) = W ( n − 1 ) + W ( n − 2 ) W ( 1 ) = 1 \left\{\begin{array}{l} W(n)=W\left(n-1\right)+W\left(n-2\right) \\ W(1)=1 \end{array}\right. {W(n)=W(n1)+W(n2)W(1)=1
复杂度分析:由递归方程可知,该算法的时间复杂度相当于斐波那契数列的时间复杂度
W ( n ) = 5 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] = O ( 2 n ) \begin{aligned} W(n)=\frac{\sqrt{5}}{5}\left[\left(\frac{1+\sqrt{5}}{2}\right)^{n}-\left(\frac{1-\sqrt{5}}{2}\right)^{n}\right]=O(2^n) \end{aligned} W(n)=55 [(21+5 )n(215 )n]=O(2n)
该算法除了输入和输出外不需要额外的存储空间,因此空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

5.2

n n n 种币值 v 1 , v 2 , . . . , v n v_1, v_2, . . . , v_n v1,v2,...,vn 和总钱数 M M M 都是正整数. 如果每种币值的钱币至多使用 1 1 1 次, 问: 对于 M M M 是否可以有一种找零钱的方法? 设计一个算法求解上述问题. 说明算法设计思想, 分析算法最坏情况下的时间复杂度.

算法设计:核心思路是采用动态规划,不断尝试并缩小问题的规模,同时考虑尽可能多的情况,可以设函数 F ( n , M ) F(n,M) F(n,M),即使用前 n n n种钱币是否可以凑出 M M M币值,其值域为 { 0 , 1 } \{0,1\} {0,1} 1 1 1代表存在至少一种找零钱的方法, 0 0 0代表不存在任何找零钱的方法。

递推方程:
F ( n , M ) = max ⁡ { F ( n − 1 , M ) , F ( n − 1 , ( M − v n ) } F ( 1 , M ) = { 1 M = v 1 0 M ≠ v 1 F ( n , M ) = 0 M < 0 \begin{array}{l} F(n,M)=\max \left\{F(n-1,M), F(n-1,\left(M-v_{n}\right)\right\}\\ F(1,M)=\left\{\begin{array}{ll} 1 & M=v_{1} \\ 0 & M≠v_{1} \end{array}\right. \\ F(n,M)=0 \quad M<0 \end{array} F(n,M)=max{F(n1,M),F(n1,(Mvn)}F(1,M)={10M=v1M=v1F(n,M)=0M<0
数据输入: n n n种币值 v [ 1.. n ] = v 1 , v 2 , . . . , v n v[1..n]=v_1, v_2, . . . , v_n v[1..n]=v1,v2,...,vn和总钱数 M M M

结果输出: 1 1 1 0 0 0,其中 1 1 1代表存在至少一种找零钱的方法, 0 0 0代表不存在任何找零钱的方法。

伪码描述:

f i n d C h a n g e   ( n , M , v ) : findChange\ (n,M,v): findChange (n,M,v):

  1. i f    y < 0 if\ \ y<0 if  y<0
  2. $then \ return\ 0 $
  3. i f    n = 1    a n d    y = v 1 if\ \ n=1\ \ and\ \ y=v_{1} if  n=1  and  y=v1
  4. $then \ return\ 1 $
  5. i f    n = 1    a n d    y ≠ v 1 if\ \ n=1\ \ and\ \ y≠v_{1} if  n=1  and  y=v1
  6. $then \ return\ 0 $
  7. / / 通过二进制或运算实现 M A X 函数 //通过二进制或运算实现MAX函数 //通过二进制或运算实现MAX函数
  8. r e t u r n   f i n d C h a n g e ( n − 1 , M , v ) ∣ f i n d C h a n g e ( n − 1 , M − v [ n ] , v ) return \ findChange(n-1,M,v)|findChange(n-1,M-v[n],v) return findChange(n1,M,v)findChange(n1,Mv[n],v)

复杂度分析:由递推方程可知,该算法的时间复杂度为
W ( n ) = O ( n M ) \begin{aligned} W(n)=O(nM) \end{aligned} W(n)=O(nM)
该算法由于通过二进制或运算实现了 M A X MAX MAX函数,因此除了输入和输出外不需要额外的存储空间,因此空间复杂度是
S ( n ) = O ( 1 ) \begin{aligned} S(n)=O(1 ) \end{aligned} S(n)=O(1)

5.3

P P P 是一台高性能服务器, T = 1 , 2 , . . . , n T = {1, 2, . . . , n} T=1,2,...,n n n n 个计算任务集合, a i a_i ai 表示任务 i i i 所申请的计算资源. 已知服务器的最大计算资源是正整数 K K K. 请确定 T T T 的一个子集 S S S, 使得 ∑ i ∈ S a i ≤ K ∑ _{i∈S} a_i ≤ K iSaiK, 且 K − ∑ i ∈ S a i K − ∑ _{i∈S} a_i KiSai 的值达到最小. 请设计一个算法求解 S S S, 并分析最坏情况下的时间复杂度.

算法设计:由题目所给的信息可以知道这实质上是一个 0 − 1 0-1 01背包问题,物品的价值和重量相等,由于这个背包问题并没有什么特殊已知条件,因此贪心算法并一定可以得到全局最优解,所以最好选用动态规划法来解决。

解决该问题的函数为 F ( n , K ) F(n,K) F(n,K),即只允许前 n n n个任务的申请,总计算资源不超过 K K K时能达到的最大计算资源,使 ∑ i ∈ S a i ∑ _{i∈S} a_i iSai的值达到最大。

递推方程:
F ( n , K ) = max ⁡ { F ( n − 1 , K ) , F ( n − 1 , K − a n ) + a n } F ( 0 , K ) = 0 F ( n , 0 ) = 0 F ( 1 , K ) = { a 1 , a 1 ≤ K 0 , a 1 > K \begin{array}{l} F(n,K)=\max \left\{F(n-1,K), F\left(n-1,K-a_{n}\right)+a_{n}\right\} \\ F(0,K)=0 \\ F(n,0)=0 \\ F(1,K)=\left\{\begin{array}{ll} a_{1}, & a_{1} \leq K \\ 0, & a_{1}>K \end{array}\right. \\ \end{array} F(n,K)=max{F(n1,K),F(n1,Kan)+an}F(0,K)=0F(n,0)=0F(1,K)={a1,0,a1Ka1>K
数据输入: n n n 个计算任务的集合 T [ 1.. n ] = { a 1 , a 2 , . . . , a n } T[1..n]=\{a_1,a_2,...,a_n\} T[1..n]={a1,a2,...,an}、服务器最大计算资源K

结果输出:布尔类型数组 S [ 1.. n ] S[1..n] S[1..n],值为 T r u e True True代表相应的任务位于 T T T的子集 S S S中,反之 F a l s e False False为该任务不在 T T T的子集 S S S中。

伪码描述:

f i n d S u b s e t   ( n , K ) : findSubset\ (n,K): findSubset (n,K):

  1. i f    n = 0   o r   K = 0 if\ \ n=0\ or\ K=0 if  n=0 or K=0
  2. $then \ return \ 0 $
  3. i f    n = 1   a n d   a 1 ≤ K if\ \ n=1\ and\ a_{1} \leq K if  n=1 and a1K
  4. $then \ return\ a_1 $
  5. i f    n = 1   a n d   a 1 > K if\ \ n=1\ and\ a_{1} > K if  n=1 and a1>K
  6. $then \ return \ 0 $
  7. x ← f i n d S u b s e t ( n − 1 , K ) x\leftarrow findSubset(n-1,K) xfindSubset(n1,K)
  8. y ← 0 y\leftarrow0 y0
  9. i f    y − a n ≥ 0 / / 防止发生 K < 0 的错误 if\ \ y-a_{n}≥0\quad//防止发生K<0的错误 if  yan0//防止发生K<0的错误
  10. t h e n   y ← f i n d S u b s e t ( n − 1 , K − a n ) + a n then \ y\leftarrow findSubset(n-1,K-a_{n})+a_{n} then yfindSubset(n1,Kan)+an
  11. i f    y ≥ x if\ \ y≥x if  yx
  12. $then \ S[n]\leftarrow True;\ return \ y $
  13. e l s e   S [ n ] ← F a l s e ;   r e t u r n   x else\ S[n]\leftarrow False;\ return\ x else S[n]False; return x

复杂度分析:由递推方程可知,该算法的时间复杂度为
W ( n ) = O ( n K ) \begin{aligned} W(n)=O(nK) \end{aligned} W(n)=O(nK)
算法需要一个布尔类型数组 S [ 1.. n ] S[1..n] S[1..n]来记录相应的任务是否位于 T T T的子集 S S S中,另外还有两个变量 x , y x,y x,y用于比较出最优情况,因此空间复杂度是
S ( n ) = O ( n + 2 ) = O ( n ) \begin{aligned} S(n)=O(n+2 )=O(n ) \end{aligned} S(n)=O(n+2)=O(n)

5.4

I I I 是一个 n n n 位十进制整数. 如果将 I I I 划分为 k k k 段, 则可得到 k k k 个整数. 这 k k k 个整数的乘积称为 I I I 的一个 k k k 乘积. 试设计一个算法, 对于给定的 I I I k k k, 求出 I I I 的最大 k k k 乘积. 尝试写出公式, 并说明算法设计思想和时间复杂度.

算法设计:核心思路依旧是采用动态规划,不断尝试并缩小问题的规模,同时考虑尽可能多的情况,设 n n n位十进制整数 I I I I 1 I 2 I 3 . . . I n I_1I_2I_3...I_n I1I2I3...In,函数 p a r t i t i o n ( I , i , j ) partition(I,i,j) partition(I,i,j)可以将 n n n位十进制整数 I I I中第 i i i位到第 j j j位拆分出来成为一个新的十进制整数。

设求解最大 k k k乘积的函数 F ( n , k ) F(n,k) F(n,k)将第 n n n位之前的部分划分为 k k k段得到的最大 k k k乘积,另外还需要找到这个函数的递推方程。

递推方程:
F ( n , k ) = { 0 n < k I 1 I 2 I 3 . . . I n k = 1 max ⁡ 1 ≤ i < n − 1 { F ( i , k − 1 ) ∗ I i + 1 I i + 2 . . . I n } k > 1   a n d   k ≤ n F(n, k)=\left\{\begin{array}{ll} 0 & n<k \\ I_1I_2I_3...I_n & k=1 \\ \max _{1 \leq i<n-1}\{F(i, k-1)*I_{i+1}I_{i+2}...I_n\} & k>1 \ and \ k \leq n \end{array}\right. F(n,k)= 0I1I2I3...Inmax1i<n1{F(i,k1)Ii+1Ii+2...In}n<kk=1k>1 and kn
数据输入: n n n位十进制整数 I I I,划分段数 k k k

结果输出: I I I的最大 k k k乘积

伪码描述:

f i n d M a x P r o d u c t   ( n , k ) : findMaxProduct\ (n,k): findMaxProduct (n,k):

  1. i f    n < k if\ \ n<k if  n<k
  2. $then \ return \ 0 $
  3. i f    k = 1 if\ \ k=1 if  k=1
  4. $then \ return\ partition(I,1,n) $
  5. P r o d u c t [ 1.. n − 1 ] ← { 0 , 0...0 } Product[1..n-1]\leftarrow\{0,0...0\} Product[1..n1]{0,0...0}
  6. f o r    i ← 1    t o    n − 1    d o / / 尝试所有可能 for \ \ i \leftarrow 1 \ \ to \ \ n-1 \ \ do\quad//尝试所有可能 for  i1  to  n1  do//尝试所有可能
  7. P r o d u c t [ i ] ← f i n d M a x P r o d u c t ( i , k − 1 ) ∗ p a r t i t i o n ( I , i + 1 , n ) Product[i]\leftarrow findMaxProduct(i,k-1)*partition(I,i+1,n) Product[i]findMaxProduct(i,k1)partition(I,i+1,n)
  8. r e t u r n   M A X ( P r o d u c t ) / / 找到 P r o d u c t 数组中最大的值返回 return \ MAX(Product)\quad //找到Product数组中最大的值返回 return MAX(Product)//找到Product数组中最大的值返回

复杂度分析:由递推方程可知,每层递归的时间复杂度是 O ( 1 + 2 + . . . + n − 1 ) O(1+2+...+n-1) O(1+2+...+n1),递归深度为 O ( k − 1 ) O(k-1) O(k1),因此该算法的时间复杂度为
W ( n ) = O ( ( k − 1 ) ( 1 + 2 + . . . + n − 1 ) ) = O ( k n 2 ) \begin{aligned} W(n)=O((k-1)(1+2+...+n-1))=O(kn^2) \end{aligned} W(n)=O((k1)(1+2+...+n1))=O(kn2)
该算法每次递归都需要一个额外的 P r o d u c t Product Product数组来记录遍历过程中求出的子乘积,以便于最后使用 M A X MAX MAX函数求出最大 k k k乘积,因此空间复杂度是
S ( n ) = O ( n ) \begin{aligned} S(n)=O(n) \end{aligned} S(n)=O(n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

drawImage 详解

背景&#xff1a; 在canvas的开发中 总会碰到drawImage这个API&#xff0c;但是里面有9个参数&#xff0c;具体代表什么意思有时候会把自己搞混乱了&#xff0c;特此记录一下&#xff0c;加深影响。 drawImage 方法有三种形态&#xff1a; drawImage(image, dx, dy) 在画布指…

【微服务】Nacos 配置管理模块

目录 一、Nacos 配置管理模块 1、配置⼀致性模型 2、Server 间的⼀致性协议 2.1、有 DB 模式&#xff08;读写分离架构&#xff09; 2.2、无 DB 模式 3、SDK 与 Server 的⼀致性协议 3.1、Nacos 1.X 3.2、Nacos 2.X 二、Nacos ⾼可⽤设计 1、全局高可用 2、同城容灾…

工信部部长金壮龙首次提到元宇宙,加快谋划布局未来产业

前言&#xff1a;继工业和信息化部、教育部、文化和旅游部、国家广播电视总局、国家体育总局等五大部门印发《虚拟现实与行业应用融合发展行动计划(2022—2026年)》之后&#xff0c;工信部部长金壮龙在接受新华社采访时提出&#xff0c;要加快人工智能、生物制造、物联网等战略…

质数判定,质因数分解,两种质数筛:埃氏筛、线性筛(欧拉筛)

质数判定 试除法&#xff0c;根据定义&#xff0c;枚举 [2,n−1][2,n-1][2,n−1] 中所有整数&#xff0c;看是否有能整除 nnn 的数 。 事实上&#xff0c;我们没有必要枚举出所有整数 abna\times bnabn&#xff0c;我们就说 aaa 和 bbb 是 nnn 的因数&#xff0c;所以因数都是…

【区块链-智能合约工程师】第四篇:Truffle框架安装和介绍(Windows)

文章目录第一次尝试安装&#xff08;fail&#xff09;简单介绍安装配置truffle命令报错&#xff1a;truffle 不是内部或外部命令truffle命令报错&#xff1a;Cannot find module fs/promises第二次尝试安装&#xff08;fail&#xff09;安装和配置npm安装ganache-cli节点仿真器…

Java高手速成│实战:应用数据库和GUI开发产品销售管理软件(2)

实战项目&#xff1a;应用数据库和GUI开发产品销售管理软件&#xff08;2&#xff09; 01、项目分析 改进实战项目——应用数据库和GUI开发产品销售管理软件&#xff08;1&#xff09;的设计和操作&#xff0c;并增加新的功能&#xff1b;利用按钮和文本框实现对数据库编程的…

荣耀破壁2022:蜕变的解法、蓄势的护法、进击的打法

“世上只有一种英雄主义&#xff0c;那就是在认清生活的真相后依然热爱生活”&#xff0c; 罗曼罗兰在《米开朗琪罗传》中写道。人如此&#xff0c;企业亦如此。12月30日&#xff0c;荣耀在新年致辞中提到&#xff1a;“真正的勇敢是在认清真相后依然热爱。”刚过去的2022年&am…

zOffice新年新版本!多项实用功能上线

2022年发生了很多大事&#xff0c;你们在2022年做过最有意义的事情是什么呢&#xff1f;或许这一年我们有很多不足&#xff0c;或许我们依旧还需努力&#xff0c;但是我们都将继续寻找人生的新篇章&#xff0c;在2023年到来之际&#xff0c;联想Filez也祝大家新年快乐&#xff…

都2023年了,诸佬们肯定熟知RabbitMQ了吧

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;曾经在某央企公司实习&#xff0c;目前入职某税务公司。本篇文章将记录和分享RabbitMQ相关的知识点。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&#xff0c;也适合复习中&#xff…

EXCEL的查找:如何按 行号+列号 进行查询, 可用indirect() + match() 或 index() + match()

0 首先用match()等取得行号&#xff0c;列号 如果想根据行号列号&#xff0c;精确查找&#xff0c;另外一个区域的数据&#xff0c;可以用如下方法 INDIRECT("Sheet2!r"&MATCH($C11,Sheet2!$A:$A,0)&"C"&MATCH(D$10,Sheet2!$1:$1,0),FALSE) …

ERR_UNSAFE_PORT浏览器安全问题导致无法访问的解决方案

前言 出发点是Java Agent内存马的自动分析与查杀&#xff0c;实际上其他内存马都可以通过这种方式查杀 本文主要的难点主要是以下三个&#xff0c;我会在文中逐个解答 1.如何dump出JVM中真正的当前的字节码 2.如何解决由于LAMBDA表达式导致非法字节码无法分析的问题 3.如何对…

短视频带货流程话术

现在短视频热度高涨&#xff0c;已经成为人们娱乐休闲的一种方式。短视频人流量大&#xff0c;已经衍生出了直播带货、橱窗链接带货等方式&#xff0c;也吸引了一批想要带货的用户。前言现在短视频热度高涨&#xff0c;已经成为人们娱乐休闲的一种方式。短视频人流量大&#xf…

JDBC(使用java语言操作数据库)

JDBC概念&#xff1a;使用Java语言操作关系型数据库的一套api&#xff08;可以用一套标准的jdbc操作所有类型的数据库&#xff0c;jdbc是接口&#xff0c;每一个数据库&#xff08;mysql、oracle、db2...&#xff09;都去实现jdbc的接口&#xff0c;每个数据库的实现类都不一样…

LeetCode:11. 盛最多水的容器

11. 盛最多水的容器1&#xff09;题目2&#xff09;思路3&#xff09;代码4&#xff09;结果1&#xff09;题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x …

2023年1月4日:fastadminApi接口开发项目时遇到的问题

SelectPage selectpage(官方文档&#xff1a;动态下拉(SelectPage) - FastAdmin框架文档 - FastAdmin开发文档) 常规用法 下面介绍一个基础的动态下拉列表示例&#xff0c;如下 <input id"c-name" data-rule"required" data-source"category/sel…

AVS3变换之IST和ISTS

IST&#xff08;Implicit Selected Transform&#xff09;是AVS3中新增的针对intra块的变换工具&#xff0c;IST对intra块提供了两种可分离的变换核&#xff0c;编码器根据RDO选择最优的变换核&#xff0c;但是对于选中的变换核不在码流中传输其索引&#xff0c;而是将其索引隐…

day34【代码随想录】贪心算法之跳跃游戏、跳跃游戏||、K次取反后最大化的数组和

文章目录前言一、跳跃游戏&#xff08;力扣55&#xff09;二、跳跃游戏 II&#xff08;力扣45&#xff09;三、K次取反后最大化的数组和&#xff08;力扣1005&#xff09;前言 1、跳跃游戏 2、跳跃游戏|| 3、K次取反后最大化的数组和 一、跳跃游戏&#xff08;力扣55&#xff…

火热的低代码到底是什么?

低代码风头正紧&#xff0c;也是最近一段时间跟云原生一起被热捧&#xff0c;不管你是做后端开发、还是前端设计、销售、售前&#xff0c;如果你没接触过低代码你都不好意思说自己在软件领域工作&#xff0c;这边文章从我的角度聊聊低代码是什么、以怎么样的方式开发、及低代码…

react笔记_05函数组件与类组件的区别之capture value特性

函数组件与类组件在写法没有好坏之分&#xff0c;性能差距也几乎可以忽略&#xff0c;而且 React 会长期支持这两种写法。 React的函数式组件和类组件之间的根本区别 在心智模型上。 函数式组件具有 capture value 特性。 capture value特性 Capture Value 从字面上可以理解…

【已解决】office提示你的许可证不是正版,你可能是盗版软件的受害者?

三步即可先看效果步骤1、下载工具2、找到 修复Office许可证明问题3、填入KMS主机&#xff0c;点击修复如何查看正在使用的 KMS 主机地址&#xff1f;先看效果 步骤 1、下载工具 工具下载&#xff1a;https://otp.landian.vip/zh-cn/ 2、找到 修复Office许可证明问题 3、填入…