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

这篇具有很好参考价值的文章主要介绍了【算法】动态规划(第五章习题解答)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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)文章来源地址https://www.toymoban.com/news/detail-783236.html

到了这里,关于【算法】动态规划(第五章习题解答)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 谭浩强【C语言程序设计】第五章习题详解

    目录 1.请画出例5.6 中给出的 3个程序段的流程图。 2.请补充例5.7程序,分别统计当“fabs(t)=1e-6”和“fabs(t)=1e-8”时执行循环体的次数。 3.输入两个正整数m 和n,求其最大公约数和最小公倍数。 4.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。 5. 求S

    2024年01月23日
    浏览(61)
  • 《python语言程序设计基础》(第二版)第五章课后习题参考答案

    第五章 函数和代码的复用 5.1 改造练习题3.5,输出更大的田字格 5.2 实现isOdd函数 5.3 实现isNum函数 5.4 实现multi函数 5.5 实现isPrime函数 5.6 输出10种生日日期格式 代码一: 代码二: 5.7 汉诺塔 注:上述代码仅供参考,若有问题可在评论区留言!

    2024年02月01日
    浏览(51)
  • 《Python 程序设计》张莉主编 第五章:程序控制结构 课后习题答案(一)

    本章主要介绍了在 Python 中对顺序结构、选择结构和循环结构的语句描述,并对列表解析和生成器表达式作简要介绍。 程序 = 算法 + 数据结构 而无论多么复杂的算法,都可以使用上述的三种基本控制中的一种或几种组成。 BTW , 这一章的作业有点长,所以打算分两次上传 (实

    2024年02月07日
    浏览(51)
  • 算法分析与设计--动态规划

    一、动态规划简介 二、动态规划求解步骤 三、动态规划典型应用 数字三角形问题 最大子段和问题 0-1背包问题 四、最长公共子序列问题 动态规划求解 五、总结 算法语言--java语言 动态规划算法通常用于求解具有某种最优性质的问题。动态规划与分治算法类似,其基本思想也

    2024年02月07日
    浏览(71)
  • 算法设计与分析复习--动态规划

    算法设计与分析复习–递归与分治(二) 与分析法类似:将原问题分解为子问题 不同点:不是通过递归的方式,而是自底向上的求解问题 矩阵连乘的次数是左矩阵行列,右矩阵行列取出左右中进行相乘。 由于矩阵乘积需要满足左矩阵列等于右矩阵的行,所以可以用一维数组

    2024年02月04日
    浏览(42)
  • 算法设计与分析实验---动态规划

    任务描述 沿着河岸摆放 N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 例如: 4 堆石子 4,5,9,4 ,可以按 (((4,5),9),4) 合并。 第一次合并得分是 9 分,合并之后石子堆是 9,9,4 第二次合并得

    2024年02月08日
    浏览(51)
  • 算法设计与分析—动态规划例题

    题目描述 求FIB数列第n项的值 输入 输入一个整数n,表示需要输出FIB数列第n项的值 输出 输出FIB数列第n项的值 样例输入  复制 样例输出  复制 提示 题目描述 长江游艇俱乐部在长江上设置了n (n=10)个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的

    2024年04月13日
    浏览(44)
  • 【算法分析与设计】动态规划(上)

       理解动态规划算法的概念 。    掌握动态规划算法的基本要素 :   (1) 最优子结构性质   (2) 重叠子问题性质   掌握设计动 态规划算法的步骤 :   (1) 找出最优解的性质,并刻划其结构特征 。   (2) 递归地定义最优值 。   (3) 以自底向上的方式计算

    2024年02月08日
    浏览(47)
  • 算法分析与设计---分治+动态规划

    1.分治法 适用条件: 问题规模缩小到一定程度容易求解 问题可以分解为若干个规模较小的 相同 子问题,即问题具有最优子结构( 使用分治法前提 ) 可以利用子问题的解合并为该问题的解( 决定是否使用分治法 ) 各个子问题 相互独立 ,即子问题之间不包含公共子问题(

    2024年02月07日
    浏览(45)
  • 【算法分析与设计】动态规划(下)

      若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的 子序列 是指 存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij 。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。   给定2个序列X和Y,当另

    2024年02月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包