国科大计算机算法分析与设计2——动态规划算法
创始人
2025-06-01 05:09:37
0

写在前面

国科大计算机算法分析与设计中动态规划算法部分,主要是一些作业题。这些题目也是动态规划方面比较经典的题目。记得上课的时候老师讲动态规划的核心就是一个多步决策过程,当时是以炮弹打飞机举例,是军事上的一个真实案例,炮弹的数量是有限的,飞机是一架一架飞的,飞机的类型不同,需要的炮弹和收益是不一样的,每一步需要决策是打还是不打。现在想想,这不是和背包问题很像吗,这个是20世纪50年代的现实问题,自此动态规划算法得到了充分的发展。
很多地方会讲动态规划最重要的是状态转移方程,确实是这样的,但是怎么想出状态转移方程呢,这个就是涉及动态规划的本质——多步决策过程,模拟成多步决策过程,比较容易找到状态转移方程。

作业1:抢劫房子得到最大收益

抢劫犯抢房子,每个房子有固定的金额,抢劫犯不能连续抢劫两栋相邻的房子,求抢劫犯可能抢到的最高总金额。假设房子之间是成直线排列的。
解法:这个问题就是一个典型的多步决策问题,每次到一个房间,只需要决定拿还是不拿。二选一的决策。如果拿的话,隔壁房间的就不能拿,否则会触发警报,不满足约束条件;如果选择不拿,就会来到下一个房间继续进行决策,拿还是不拿。
为了分析问题,我们定义一下房间顺序,假设有n个房间,编号分别为1到n,为了叙述方便,假设从最后一个房间决定拿还是不拿,依次向前。第k个房间的钱定义为a[k]a[k]a[k],前k个房间能偷到的最大钱数定义为value[k]value[k]value[k]。如果拿了第n个房间的钱,那就拿不了第n-1个房间的钱,但是总钱数上会加上第n个房间的钱。也即是:
value[n]=value[n−2]+a[n]value[n]=value[n-2]+a[n]value[n]=value[n−2]+a[n]
如果没有拿第n个房间的前,那么就到第n-1个房间决定拿不拿。也即是:
value[n]=value[n−1]value[n]=value[n-1]value[n]=value[n−1]
为了拿到最多的钱,只需要上面两种情况取最大值:
value[n]=max{value[n−2]+a[n],value[n−1]}value[n]=max\left\{value[n-2]+a[n],value[n-1] \right\}value[n]=max{value[n−2]+a[n],value[n−1]}
在这里插入图片描述
在这里插入图片描述
如果房子之间的排列是一个环,不是一条直线,那么只需要破环转线就行,考虑1到n-1和2到n这两种情况,这两种情况取最大值即可,最大值就是成环的时候,能够抢到的最多钱。

作业2:丑数

给定整数n,找出并返回第n个丑数。丑数是只包含质因数2、3、5的正整数。
解法:第n个丑数一定是第1个到第n-1个丑数中的某个数乘上2、3或5得到的。
定义p2p3p5三个指针,表示下一个丑数是当前指针指向的丑数乘以对应的质因数。OPT[i],表示第i个丑数,每次决策下一个丑数是由p2p3p5中的哪个指针指向的丑数乘得。更新相应指针。
在这里插入图片描述
在这里插入图片描述

作业3:二叉搜索树个数

给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
输 入:数字n。
输 出:二叉搜索树的数目。
在这里插入图片描述
解答: 对于以1~n为节点值组成的二叉树中,1~n每个数都可以作为根节点的节点值,当以i作为根节点时,1~(i-1) 这些数位于根节点的左子树中,(i+1)~n这些数位于根节点的右子节点中,即当以i作为根节点时有2个子问题,而1~n每个数都可以作为根节点的节点值,所以总共有2n个子问题。
以(i+1)~n为节点组成二叉搜索树的数目等于以1~(n-i)为节点组成二叉搜索树的数目。
在这里插入图片描述

在这里插入图片描述

作业4:最大整除子集

给定一个正整数数组,找其中最大的一个子集,要求该集合中任意两个元素都能整除
输 入:正整数数组
输 出:符合条件的最大子集长度
解法:如果已存在某个整除子集,若新的元素可以整除该子集中的最大值,则可加入该子集。
OPT[i],表示包含第i个元素的最大整除子集的长度
决策已存在的子集能否加入第i个元素
在这里插入图片描述

作业5:目标和

给定一个非负整数数组,a1, a2, …, an, 和一个目标数 S。现在有两个符号 + 和 – ,并且对于数组中的任意一个整数,你都可以从 + 和 – 中选择一个符号添加在前面。返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
在这里插入图片描述
可以看到这些数值都是正整数,需要给这些正整数添加正负号,使得结果等于target,每个正整数都只有两种情况,要么是正号,要么是负号,这和背包问题很像。因为直接求解会有负数的情况产生,因此可以把问题变形一下,也能降低复杂度,我们假设加负号的所有正整数的和为sumnegsum_{neg}sumneg​,假设所有的正整数的和为sumsumsum,那么就可以得到(sum−sumneg)−sumneg=target(sum-sum_{neg})-sum_{neg}=target(sum−sumneg​)−sumneg​=target,由此可得sumneg=sum−target2sum_{neg}=\frac{sum-target}{2}sumneg​=2sum−target​。原问题可以转化为我们选哪些数当作加负号的,没选中的就代表加了正数,因此就变成了选不选每个数,也就是说对于每个正整数,有两个选择,一个是选,一个是不选。这就和背包问题很像了,可以建立一个二维的数组dp[][]dp[][]dp[][],在行方向就代表了每一个数,长度就是输入数组的长度nums.length()nums.length()nums.length(),在列的方向就是要计算出的目标值sumnegsum_{neg}sumneg​,最后一个元素dp[nums.length()][sumneg]dp[nums.length()][sum_{neg}]dp[nums.length()][sumneg​]代表了在有nums.length()nums.length()nums.length()个元素的情况下,计算出目标值等于sumnegsum_{neg}sumneg​的情况有多少种。
以数组中第k个元素为例,第k个元素的值就是nums[k]nums[k]nums[k],我们假设要计算dp[k][j]dp[k][j]dp[k][j],也就是在k个元素的情况下,等于j的情况数有多少种,这里对于第k个元素有两种情况,选还是不选。这里分情况讨论:
(1)当j dp[k][j]=dp[k−1][j]dp[k][j]=dp[k-1][j]dp[k][j]=dp[k−1][j]
(2)当j>=nums[k]j>=nums[k]j>=nums[k],这里对于第k个元素就有两种情况,选还是不选。如果选第k个元素,那就是说前k-1个元素加一起的值是j−nums[k]j-nums[k]j−nums[k],那么在选第k个元素的情况下,有dp[k−1][j−nums[k]]dp[k-1][j-nums[k]]dp[k−1][j−nums[k]]这么多种情况;另一种就是不选第k个元素,不选第k个元素,那就是说前k-1个元素加一起的值是jjj,那么在不选第k个元素的情况下,有dp[k−1][j]dp[k-1][j]dp[k−1][j]这么多种情况。因为最终是问总的情况数,选和不选都算情况数,所以两个情况应该是相加的。也就是:
dp[k][j]=dp[k−1][j]+dp[k−1][j−nums[k]]dp[k][j]=dp[k-1][j]+dp[k-1][j-nums[k]]dp[k][j]=dp[k−1][j]+dp[k−1][j−nums[k]]
在这里插入图片描述

作业6:带冷冻期的股票交易

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
• 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
• 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(来源:https://www.programmercarl.com/0309.%E6%9C%80%E4%BD%B3%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E6%97%B6%E6%9C%BA%E5%90%AB%E5%86%B7%E5%86%BB%E6%9C%9F.html)

作业7:回文子串数目

给定一个字符串,计算这个字符串中有多少个回文子串。具有不同开 始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不 同的子串。
示例:
输入:“abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
在这里插入图片描述

作业8:最小编辑距离

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所 使用的最少操作数 。(插入、删除、替换)
示例:
Input: word1 = “horse”, word2 = “ros”
Output: 3
Explanation:
horse -> rorse (replace ‘h’ with ‘r’)
rorse -> rose (remove ‘r’)
rose -> ros (remove ‘e’)
我们需要运用题目中的三种操作来把word1转换成word2。首先,分析一下这3种操作。假设给定A,B两个单词,那对于A,B来说,只需要在A上进行操作,最终让A=B即可。我们用D[i][j]来表示A的前i个字母和B前J个字母之间的编辑距离,当我们想获得D[i][j]时,我们可以利用上述三种操作实现A=B。
1.在D[i-1][j]的基础上(此时已经知道A[:i-1]=B[:j]),所以在A中删除最后一个元素即可。
2.在D[i][j-1]的基础上(此时A[:i]=B[:j-1]),所以在A上插入B[j]即可
3.在D[i-1][j-1]的基础上(此时A[:i-1]=B[:j-1]]),所以把A[i]修改成B[j]即可,但注意如果A[i]=B[j],我们不需要做任何操作。
在这里插入图片描述

        for i in range(1, n + 1):for j in range(1, m + 1):left = D[i - 1][j] + 1down = D[i][j - 1] + 1left_down = D[i - 1][j - 1] if word1[i - 1] != word2[j - 1]:left_down += 1D[i][j] = min(left, down, left_down)return D[n][m]

(来源:https://blog.csdn.net/litt1e/article/details/105344345)
参考:算法课动态规划答疑ppt

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...