目录
1.动态规划法和分治法有什么共同点?这两种技术之间最主要的不同点是什么?
a.说明直接应用递归式(8.3)求解币值最大化问题的时间效率是指数级的。
b.说明通过穷举查找求解币值最大化问题的时间效率至少是指数级的。
4.对于币值为1,3,5且n=9的找零问题,利用动态规划算法求其所有解。
5.对于有些单元格不可达的硬币收集问题,如何修改原来的动态规划算法?应用新算法求解下图问题,其中不可达的单元格用×表示。对于这块板而言有多少条最优路径?
[6.切割木棍问题 为下列问题设计一个动态规划算法。已知小木棍的销售价格p₁和长度i相关,i=1,2,...,n,如何把长度为n的木棍切割为若干根长度为整数的小木棍,使得所能获得的总销售价格最大?该算法的时间效率和空间效率各是多少?](#6.切割木棍问题 为下列问题设计一个动态规划算法。已知小木棍的销售价格p₁和长度i相关,i=1,2,…,n,如何把长度为n的木棍切割为若干根长度为整数的小木棍,使得所能获得的总销售价格最大?该算法的时间效率和空间效率各是多少?)
[7. 最短路径数量 国际象棋中的车可以水平或竖直移到棋盘中同行或同列的任何一格。将车从棋盘的一角移到另一对角,有多少条最短路径?路径的长度由车所经过的方格数(包括第一格和最后一格)来度量。使用下列方法求解该问题。](#7. 最短路径数量 国际象棋中的车可以水平或竖直移到棋盘中同行或同列的任何一格。将车从棋盘的一角移到另一对角,有多少条最短路径?路径的长度由车所经过的方格数(包括第一格和最后一格)来度量。使用下列方法求解该问题。)
[8.最小总和问题 将正整数排成等边三角形,三角形的底边有n个数,下图给出了n=4的一个例子。从三角形顶点出发通过一系列相邻整数(在图中用圆圈表示),如何使得到达底边时的总和最小?为这个问题设计一个动态规划算法并给出时间效率。](#8.最小总和问题 将正整数排成等边三角形,三角形的底边有n个数,下图给出了n=4的一个例子。从三角形顶点出发通过一系列相邻整数(在图中用圆圈表示),如何使得到达底边时的总和最小?为这个问题设计一个动态规划算法并给出时间效率。)
[9.二项式系数 设计一个高效的算法计算二项式系数C(n,k),该算法不能利用乘法。给出算法的空间效率和时间效率。](#9.二项式系数 设计一个高效的算法计算二项式系数C(n,k),该算法不能利用乘法。给出算法的空间效率和时间效率。)
[11.最大子方阵 对一个m×n布尔矩阵B,找出其元素均为0的最大子方阵。设计一个动态规划算法并给出时间效率。(该算法可能会用于在计算机屏幕中寻找最大空白方形区域或者是选择建筑地点。)](#11.最大子方阵 对一个m×n布尔矩阵B,找出其元素均为0的最大子方阵。设计一个动态规划算法并给出时间效率。(该算法可能会用于在计算机屏幕中寻找最大空白方形区域或者是选择建筑地点。))
[12.世界大赛的胜率 考虑A和B两支队伍,正在进行一系列比赛,直到一个队赢得了n场比赛为止。假设A队赢得每场比赛的概率都是相同的,即等于p,而A队丢掉比赛的概率是q=1-p(因此,就不存在平局了)。当A队还需要i场胜利才能赢得系列赛,B队还需要j场胜利才能赢得系列赛时,A队赢得系列赛的概率为P(i,j)。](#12.世界大赛的胜率 考虑A和B两支队伍,正在进行一系列比赛,直到一个队赢得了n场比赛为止。假设A队赢得每场比赛的概率都是相同的,即等于p,而A队丢掉比赛的概率是q=1-p(因此,就不存在平局了)。当A队还需要i场胜利才能赢得系列赛,B队还需要j场胜利才能赢得系列赛时,A队赢得系列赛的概率为P(i,j)。)
a.为P(i,j)建立一个可以在动态规划算法中使用的递推关系。
b.如果A队赢得一场比赛的概率是0.4,该队赢得一个7场系列赛的概率是多少?
c.为解决该问题写一个动态规划算法的伪代码,并确定它的时间和空间效率。
1.动态规划法和分治法有什么共同点?这两种技术之间最主要的不同点是什么?
共同点:都将问题分解为更小的子问题,通过求解子问题再合并得到原问题的解
不同点:分治法的子问题相互独立、不重叠 ;动态规划的子问题相互重叠、有重复 ,需要记录子问题解以避免重复计算。
2.求解币值最大化问题的一个实例5,1,2,10,6。
规则:
- 不能选相邻硬币
- 选硬币,使得总面值最大
分析:如果取了第n个,那么第n-1个就不能取,如果n-1取了,n就不能取
即C(n)=max(C(n-1),C(n-2)+vn)
所以递推式为:


因此最多取到15
3.
a.说明直接应用递归式(8.3)求解币值最大化问题的时间效率是指数级的。
递归的递推式为

递归中每个子问题会被重复计算,比如F(n-1)又会计算n-2与n-3,而F(n-2)又会计算n-3和n-4
因此直接递归的时间效率是指数级:O(2^n)
b.说明通过穷举查找求解币值最大化问题的时间效率至少是指数级的。
穷举思路:
每个硬币有两种选择:选 或 不选 ,但不能相邻。
我们只需要下界:即使不考虑 "不能相邻",n 个硬币也有:2^n种可能子集,此时和递归就半斤八两了。
考虑 "不能相邻" 后,合法子集数量仍然满足:需要检查指数级数量 的子集,因此仍然是指数级。
4.对于币值为1,3,5且n=9的找零问题,利用动态规划算法求其所有解。
也就是用最少硬币数 找零,求所有最优解
dp[i]表示为找零i需要dp[i]张纸币
初始dp[0]为无穷大,
dp[i] = min(dp[i], dp[i - c] + 1),c为所给的币值
计算如下:
dp[0] = 0
dp[1] = dp[0]+1 = 1
dp[2] = dp[1]+1 = 2
dp[3] = min(dp[2]+1, dp[0]+1) = 1
dp[4] = min(dp[3]+1, dp[1]+1) = 2
dp[5] = min(dp[4]+1, dp[2]+1, dp[0]+1) = 1
dp[6] = min(dp[5]+1, dp[3]+1) = 2
dp[7] = min(dp[6]+1, dp[4]+1) = 3
dp[8] = min(dp[7]+1, dp[5]+1) = 2
dp[9] = min(dp[8]+1, dp[6]+1, dp[4]+1) = 3
5.对于有些单元格不可达的硬币收集问题,如何修改原来的动态规划算法?应用新算法求解下图问题,其中不可达的单元格用×表示。对于这块板而言有多少条最优路径?

- 把不可达单元格(×) 的价值设为 -∞(无穷小) ,表示不能进入。
- 递推公式保持不变:dp[i][j]=当前硬币+max(dp[i−1][j], dp[i][j−1])
- 如果上方 和左侧 都是不可达,则当前单元格也不可达。
6.切割木棍问题 为下列问题设计一个动态规划算法。已知小木棍的销售价格p₁和长度i相关,i=1,2,...,n,如何把长度为n的木棍切割为若干根长度为整数的小木棍,使得所能获得的总销售价格最大?该算法的时间效率和空间效率各是多少?
设:
- dp[i] = 长度为 i 的木棍能获得的最大收益
- p[i] = 长度为 i 的价格
递推公式为:

输入:n, 价格数组 p[1..n]
输出:最大总收益 dp[n]
dp[0] = 0
for i = 1 to n:
dp[i] = -∞
for k = 1 to i:
dp[i] = max(dp[i], p[k] + dp[i - k])
return dp[n]
当p[k]+dp[i-k]是较大值的时候,就等于从n上减去了长度k的木棍时最有价值,当内循环结束时,就选出了最有价值的k
时间效率为Θ(n^2),空间效率为Θ(n)
7. 最短路径数量 国际象棋中的车可以水平或竖直移到棋盘中同行或同列的任何一格。将车从棋盘的一角移到另一对角,有多少条最短路径?路径的长度由车所经过的方格数(包括第一格和最后一格)来度量。使用下列方法求解该问题。
a.动态规划算法
设dp[i][j]表示从(0,0)到(i,j)的路径方案数量,
dp[0][0]=1,表示到自己有一条路径
其余dp都初始化为0;
则状态转移方程为dp[i][j]=dp[i-1][j]+dp[i][j-1]。表示可以从左边和上边过来的路径
保证边界条件:
第一行:只能一直右走,所以dp[0][j]=1
第一列:只能一直下走,所以dp[i][0]=1
最终返回dp[n-1][n-1]就是要的答案
b.基本排列组合
最短路径必须:
- 向右走:n−1 步
- 向下走:n−1 步
- 总步数:2 (n−1) 步
在 2 (n−1) 步 中选 n−1 步向右(剩下向下)。
排序组合为:

8.最小总和问题 将正整数排成等边三角形,三角形的底边有n个数,下图给出了n=4的一个例子。从三角形顶点出发通过一系列相邻整数(在图中用圆圈表示),如何使得到达底边时的总和最小?为这个问题设计一个动态规划算法并给出时间效率。

同样设计dp[i][j],表示从(0,0)到(i,j)的最小和
其中初始化dp[0][0]=v[0][0]; dp[i][0]=v[i][0]+dp[i-1][j];
将题给的三角形转换成一个数组,0<=i<=j<=n的三角阵,则(i,j)只能从左上角和上边两个方向过来
则有dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+v[i][j]
最终遍历dp数组的最后一行,求出答案
效率明显为Θ(n^2)
9.二项式系数 设计一个高效的算法计算二项式系数C(n,k),该算法不能利用乘法。给出算法的空间效率和时间效率。
二项式系数满足:
C(n,k)=C(n−1,k−1)+C(n−1,k)
边界条件:
C(n,0)=1,C(n,n)=1
则递推式:
dp[i][0] = 1
dp[i][i] = 1
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
函数 Binomial(n, k):
创建二维数组 dp[n+1][k+1]
对于 i from 0 to n:
dp[i][0] = 1
对于 i from 0 to n:
dp[i][i] = 1
对于 i from 2 to n:
对于 j from 1 to min(i-1, k):
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
返回 dp[n][k]
时间和空间效率都是Θ(nk)
10.有向无环图的最长路径
a.设计一个高效算法找出有向无环图中最长路径的长度。(这个问题无论是作为其他动态规划应用的原型,或者就其自身而言都是很重要的。当一个项目由若干具有前趋依赖的任务组成时,它决定了完成该项目所需的最少时间。)
用动态规划的思路来看,到某点的最长路径 = max (到它前驱点的最长路径) + 边权 / 点权
用一个邻接矩阵记录点位,dp[v] 表示 从起点到结点 v 的最长路径长度
dp[0]=0, 其余为无穷小
dp[i]=max(dp[i], dp[u]+w(u,v))
最终返回dp[n]
b.将币值最大化问题变换为寻找有向无环图的最长路径问题。
- 一排硬币:v1,v2,...,vn
- 不能选相邻硬币
- 求选出硬币总价值最大
将每个硬币视为一个点,加两类边:
- 不选第 i 个硬币 :i→i+1,边权 0
- 选第 i 个硬币 :i→i+2,边权 vi(选了 i 就不能选 i+1,直接跳到 i+2)
币值最大化问题的最优解 = 该 DAG 从 0 到 n 的最长路径长度
11.最大子方阵 对一个m×n布尔矩阵B,找出其元素均为0的最大子方阵。设计一个动态规划算法并给出时间效率。(该算法可能会用于在计算机屏幕中寻找最大空白方形区域或者是选择建筑地点。)
dp[i][j] = 以单元格 (i,j) 作为右下角 的、全为 0 的最大正方形的边长。
如果当前格子B[i][j]=0,dp[i][j] = min( dp[i-1][j], dp[i][j-1], dp[i-1][j-1] ) + 1
初始化dp[i][j] = 0
同时遍历整个 dp 表,最大值 就是最大全 0 方阵的边长。
输入:m×n 布尔矩阵 B
输出:最大全0子方阵的边长 maxLen
1. 创建 m×n 的 dp 矩阵
2. maxLen = 0
3. 初始化第一行和第一列:
for j from 0 to n-1:
dp[0][j] = 1 if B[0][j] == 0 else 0
maxLen = max(maxLen, dp[0][j])
for i from 0 to m-1:
dp[i][0] = 1 if B[i][0] == 0 else 0
maxLen = max(maxLen, dp[i][0])
4. 填充 dp 表:
for i from 1 to m-1:
for j from 1 to n-1:
if B[i][j] == 0:
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
maxLen = max(maxLen, dp[i][j])
else:
dp[i][j] = 0
5. return maxLen
时间和空间效率都是Θ(mn),
12.世界大赛的胜率 考虑A和B两支队伍,正在进行一系列比赛,直到一个队赢得了n场比赛为止。假设A队赢得每场比赛的概率都是相同的,即等于p,而A队丢掉比赛的概率是q=1-p(因此,就不存在平局了)。当A队还需要i场胜利才能赢得系列赛,B队还需要j场胜利才能赢得系列赛时,A队赢得系列赛的概率为P(i,j)。
a.为P(i,j)建立一个可以在动态规划算法中使用的递推关系。
每场比赛:
- A 赢的概率:p → 下一个状态:P(i-1, j)
- A 输的概率:q=1-p → 下一个状态:P(i, j-1)
所以递推式:

b.如果A队赢得一场比赛的概率是0.4,该队赢得一个7场系列赛的概率是多少?
-
P(1,1) = 0.4×1 + 0.6×0 = 0.4
-
P(1,2) = 0.4×1 + 0.6×P(1,1) = 0.4 + 0.6×0.4 = 0.64
-
P(1,3) = 0.4×1 + 0.6×0.64 = 0.784
-
P(1,4) = 0.4×1 + 0.6×0.784 = 0.8704
-
P(2,1) = 0.4×P(1,1)+0.6×0 = 0.16
-
P(2,2) = 0.4×P(1,2)+0.6×P(2,1) = 0.4×0.64+0.6×0.16 = 0.352
-
P(2,3) = 0.4×P(1,3)+0.6×P(2,2) = 0.5248
-
P(2,4) = 0.4×P(1,4)+0.6×P(2,3) = 0.64288
-
P(3,1) = 0.4×P(2,1) = 0.064
-
P(3,2) = 0.4×P(2,2)+0.6×P(3,1) = 0.1792
-
P(3,3) = 0.4×P(2,3)+0.6×P(3,2) = 0.31744
-
P(3,4) = 0.4×P(2,4)+0.6×P(3,3) = 0.447872
-
P(4,1) = 0.4×P(3,1) = 0.0256
-
P(4,2) = 0.4×P(3,2)+0.6×P(4,1) = 0.08704
-
P(4,3) = 0.4×P(3,3)+0.6×P(4,2) = 0.178176
-
P(4,4) = 0.4×P(3,4)+0.6×P(4,3) = 0.289856
c.为解决该问题写一个动态规划算法的伪代码,并确定它的时间和空间效率。
输入:n(需赢场数), p(A单场胜率)
输出:P(n,n)
创建 (n+1)×(n+1) 二维数组 dp
q = 1 - p
// 初始化边界
for j from 0 to n:
dp[0][j] = 1
for i from 0 to n:
dp[i][0] = 0
// 填表
for i from 1 to n:
for j from 1 to n:
dp[i][j] = p * dp[i-1][j] + q * dp[i][j-1]
return dp[n][n]