补充证明:为什么长度恰好是 n + m − L
构造上界:把长度 L 的 LCS 共享一次,其余字符各保留一次,得到长度 n+m−L 的公共超序列。
下界:在任意公共超序列中,固定 A 与 B 的两套嵌入位置。两套位置重叠处的字符按顺序组成 A、B 的一个公共子序列,所以重叠数至多 L。位置并集至少有 n+m−L 个;超序列长度至少这么大。上下界相等,构造最优。
动态规划续篇 · 按 PPT 章节归类 · 课堂 + 补录
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:We stopped at LCS
这次的主线是:先说清“小问题还允许什么”,再用已经算好的答案拼出大答案。字符串限制前缀;矩阵链限制区间;树限制子树及根的状态;有环图再增加“边数上限”或“允许的中间点”。
| 部分 | 怎样把问题变小 | 新内容与来源 |
|---|---|---|
| 字符串 | 缩短 A、B 的前缀 | 课堂 · SCS、编辑距离 · p61–63 |
| 区间 | 按最后一次运算切成左右两个连续区间 | 课堂 · 矩阵链、表达式括号化 · p65–74 |
| 树 | 先处理孩子子树,保留根能否再被使用的信息 | 课堂 · 匹配计数与优化 · p77–81 |
| DAG | 按拓扑顺序处理最后一条边的起点 | 补录 · DAG 与流水线 · p83–91 |
| 一般有向图 | 减少允许的边数,或减少允许的中间顶点 | 补录 · Bellman–Ford、Floyd–Warshall · p93–103 |
“课件原文”保留正式题目或定义,并附中文翻译;教授的解释融入对应段落。“补充推导”“自写示例”表示整理时补全的内容。全文沿用课程的常数时间算术模型;计数值很大时,实际大整数运算的位成本需另计。
Two Parameters, Constant Recurrence
延续第五周的双参数 DP。这里每个状态只比较常数个候选;本周继续整理最短公共超序列与编辑距离。
PPT 实际 p61–63Shortest Common Supersequence
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:shortest common super sequence
Instance: two sequences A = ⟨a₁, a₂, ... aₙ⟩ and B = ⟨b₁, b₂, ... bₘ⟩. Task: find a shortest common supersequence of A and B, i.e., a shortest possible sequence that both A and B are subsequences of.
输入两条序列 A、B。找一条最短序列,使 A 与 B 都是它的子序列。
最短公共超序列(Shortest Common Supersequence, SCS)要找一条尽量短的新序列,让 A、B 都能作为它的子序列。可以跳过字符,但相对次序要保留。
做法:先求一条最长公共子序列 LCS,再沿它的匹配位置从左向右合并。每遇到一个共同字符,就先放入两串各自尚未放入的前置字符,再把该共同字符放一次;最后放入两串剩余尾部。两串内部的顺序始终不变。
设 n = |A|,m = |B|,L = LCS 的长度。
SCS 的最短长度 = n + m − L。代价:复用第五周的 LCS 算法,时间 O(nm),完整表空间 O(nm);恢复 LCS 后合并两串再用 O(n+m) 时间。
构造上界:把长度 L 的 LCS 共享一次,其余字符各保留一次,得到长度 n+m−L 的公共超序列。
下界:在任意公共超序列中,固定 A 与 B 的两套嵌入位置。两套位置重叠处的字符按顺序组成 A、B 的一个公共子序列,所以重叠数至多 L。位置并集至少有 n+m−L 个;超序列长度至少这么大。上下界相等,构造最优。
Edit Distance
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:minimum cost to transform
Instance: Given two text strings A of length n and B of length m, you want to transform A into B. You are allowed to insert a character, delete a character and to replace a character with another one. An insertion costs cI, a deletion costs cD and a replacement costs cR. Task: find the smallest possible cost to transform A into B.
给定长度分别为 n、m 的字符串 A、B。允许以指定代价插入、删除或替换字符,求把 A 转换成 B 的最小总代价。
编辑距离(Edit Distance)把 A 改成固定目标 B,并使总代价最小。允许插入、删除、替换;分别记非负代价 cI、cD、cR。B 是目标,下面的操作都作用在当前 A 上。
E(i,j) = 把 A[1..i] 变成 B[1..j] 的最小总代价。
i、j 是两个前缀的长度,允许为 0。
E(0,0) = 0
E(i,0) = i × cD // 删完 A 的 i 个字符
E(0,j) = j × cI // 从空串插入 B 的 j 个字符教授从“目标末尾 B[j] 怎样被对应”解释递推:它可以对应 A[i],也可以对应 A 中更早的字符,或者对应一个新插入的字符。于是只需处理一步,就能回到同一形式的较短前缀问题。
| 选择 | 此步做什么 | 所需较小状态 | 候选代价 |
|---|---|---|---|
| 删除 | 删除 A[i],目标 B[j] 仍待匹配 | E(i−1,j) | cD + E(i−1,j) |
| 插入 | 先把整个 A 前缀改成 B[1..j−1],最后补入 B[j] | E(i,j−1) | cI + E(i,j−1) |
| 保留 / 替换 | 把两个末尾对齐;相同免费,不同付替换费 | E(i−1,j−1) | E(i−1,j−1) + δ,δ = 0 或 cR |
当 i,j ≥ 1:
δ = 0(A[i] = B[j]),否则 δ = cR。
E(i,j) = min(
cD + E(i−1,j),
cI + E(i,j−1),
δ + E(i−1,j−1)
)用字符对齐表示任意转换:A 的字符要么删除,要么与 B 的某个字符按顺序对齐;未被对应的 B 字符由插入产生。最后一列只有“删除 A[i]”“插入 B[j]”“对齐 A[i] 与 B[j]”三种类型。
删除最后一列后,剩余转换对应表中的一个子问题;若它不是最优,替换成更便宜的前缀转换就能改善整体。反过来,每个候选都能拼成一个合法转换。按 i+j 归纳,取三者最小值就是 E(i,j)。这里说明的是代价最小,不要求编辑脚本唯一。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:increasing order of what is effectively I plus J
行 i 表示 A 的前缀长度,列 j 表示 B 的前缀长度。当前格只依赖“上、左、左上”。先填基础行和列,再按行从上到下、每行从左到右填。最后答案是 E(n,m)。
自写示例:cat → coat,三种操作代价均为 1。E(1,2) 对应 c → co,插入 o 只需 1;最终 E(3,4)=1。
绿色:本步计算或改善的状态;蓝色:相关依赖。演示帮助观察过程,一般正确性由正文证明。
时间:共 (n+1)(m+1) 个状态,每个比较常数个候选,为 O(nm)(两串非空时);包含空串的统一写法为 O((n+1)(m+1))。完整表空间同阶。恢复操作时为每格记录获胜选择,再从 (n,m) 回到 (0,0)。
Two Parameters, Linear Recurrence
区间的两个端点定义状态;枚举最后一次运算的切点,合并两个更短区间。“线性”指一个状态可能需要枚举线性多个切点,总时间通常为三次。
PPT 实际 p65–74Matrix chain multiplication
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:matrix multiplication is associative
Instance: a compatible sequence of matrices A₁A₂...Aₙ, where Aᵢ is of dimension sᵢ₋₁×sᵢ. Task: group them in such a way as to minimise the total number of multiplications performed to find the product matrix.
给定一条维度兼容的矩阵链,Aᵢ 的尺寸为 sᵢ₋₁×sᵢ。添加括号,使求整个乘积所需的标量乘法总数最少。
本题决定矩阵相乘的括号位置。矩阵的前后顺序固定;结合律允许 A(BC)=(AB)C,交换 A、B 的位置通常不合法。要最小化的是标量乘法次数,不是把 n 个矩阵连成一个时固定需要的 n−1 次矩阵合并。
A 是 m×q,B 是 q×p:
AB 是 m×p。
AB 的每个元素要做 q 次标量乘法,共 m×p 个元素。
所以一次矩阵合并的标量乘法数 = m×q×p。| 课件 p66:A 10×100、B 100×5、C 5×50 | 先合并 | 再合并 | 总代价 |
|---|---|---|---|
| (AB)C | AB:10×100×5 = 5,000;结果 10×5 | (AB)C:10×5×50 = 2,500 | 7,500 |
| A(BC) | BC:100×5×50 = 25,000;结果 100×50 | A(BC):10×100×50 = 50,000 | 75,000 |
教授让大家记住的基础事实就是“外维度 × 共同维度 × 外维度”。先选出括号方案,再按这个规则累计每次合并的代价。DP 本身只处理这些尺寸和代价,无需真的存储或乘出矩阵元素。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:prefixes are not the correct
先试 F(j)=计算 A₁…Aⱼ 的最少代价。若最后一次合并发生在 Aₖ 与 Aₖ₊₁ 之间,左块 A₁…Aₖ 的答案是 F(k),但右块 Aₖ₊₁…Aⱼ 也需要一个最优答案;它不是从 A₁ 开始,F 没有保存它。
改用区间状态:
C(i,j) = 计算 Aᵢ₊₁ Aᵢ₊₂ … Aⱼ 的最少标量乘法数。
0 ≤ i < j ≤ n;左端不含 i,右端包含 j。
在 i < k < j 处切开:
左块 (i,k],右块 (k,j],都属于同一类区间子问题。例如 C(3,8) 处理 A₄…A₈。四个切点 k=4,5,6,7,分别依赖 C(3,k) 与 C(k,8)。区间中不允许跳过矩阵,因此这里的 contiguous subsequence 是连续的一段。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:left exclusive, right inclusive
用上一节的 C(i,j)。左块合并后的尺寸一定是 sᵢ×sₖ,右块一定是 sₖ×sⱼ;它们的最终尺寸与各自内部怎样加括号无关。这使左右两块可以各自求最优,再独立合并。
基础:C(i,i+1) = 0 // 一个矩阵无需合并
当 j−i > 1:
C(i,j) = min_{i<k<j} [ C(i,k) + C(k,j) + sᵢsₖsⱼ ]
最终答案:C(0,n)。| 组成 | 为何必须计算 |
|---|---|
| C(i,k) | 先把左半条链合成一个矩阵 |
| C(k,j) | 先把右半条链合成一个矩阵 |
| sᵢsₖsⱼ | 把刚得到的两个矩阵做最后一次合并 |
顺序:按区间长度 ℓ=j−i 从 1 增加到 n。左右块长度都严格小于 ℓ,所以依赖已经完成。课件表格上,C(i,k) 在当前格左边,C(k,j) 在当前格下方;按普通“从上到下逐行”会先遇到未算出的下方依赖。
绿色:本步计算或改善的状态;蓝色:相关依赖。演示帮助观察过程,一般正确性由正文证明。
取任意最优括号方案,其最后一次合并必有某个切点 k。若左块或右块不是各自最优,就能用更便宜且尺寸相同的方案替换,降低整体代价。因此最优方案属于某个候选。每个候选也都能合法拼成整体;取最小值即最优。对区间长度归纳即可连接全部子问题。
同时保存 split(i,j)=一个使候选最小的 k。恢复时输出左区间的括号、右区间的括号,再包在一起;长度为 1 时直接输出该矩阵名。示例在 C(0,3) 选 k=2,恢复为 ((A₁A₂)A₃)。值 C 与选择 split 的角色不同。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:the actual number of bracketings
矩阵链有 O(n²) 个区间,每个区间尝试 O(n) 个切点,因此标准算法时间 O(n³),空间 O(n²)。教授进一步提出:短区间只有少量切点,精确求和能否把次数降到严格低于三次?
还可以把一次切点尝试看成选择三个严格递增的边界 i<k<j;从 n+1 个边界中选三个,正好得到同一个组合数。这是对当前逐个枚举切点算法的分析。
计数括号方案(不是求最便宜的方案):
T(1) = 1
T(n) = Σ[k=1..n−1] T(k) × T(n−k)
n = 1,2,3,4,5 时,T(n) = 1,1,2,5,14。
T(n) = Catalan(n−1)。为什么这里相乘再相加?固定最后切点,左右可以独立选择括号方案,所以相乘;最后切点不同代表互斥情况,所以相加。教授指出:计数只与链长有关,不需要两个端点;求代价则取决于具体尺寸,必须保留区间位置。
Cq = binom(2q,q)/(q+1),本题 T(n)=Cₙ₋₁。方案数随 n 指数增长,因此枚举所有括号远比 DP 昂贵。课件 p68 列出的其他组合对象是延伸阅读;这里聚焦矩阵链中的计数含义。
Maximising an expression
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:the maximum value and also the minimum value
Instance: a sequence of numbers with operations +, −, × in between, for example 1 + 2 − 3 × 6 − 1 − 2 × 3 − 5 × 7 + 2 − 8 × 9. Task: place brackets in a way that the resulting expression has the largest possible value.
给定数字与其间的加、减、乘运算。保持它们的先后次序,添加括号,让表达式结果尽可能大。
固定数字和 +、−、× 的先后次序,只改变括号,使表达式结果最大。仍然枚举最后一次运算的位置,但“左右都取最大”只对加法安全:减法希望左大右小,乘法还会受到正负号影响。
下面是课件 p74 留作练习的完整补充解法。设数字是 x₁…xₙ,opₖ 是 xₖ 与 xₖ₊₁ 之间的运算符;Lo(i,j)、Hi(i,j) 分别是连续子表达式 xᵢ…xⱼ 的最小、最大可达值。这里改用两端都包含的区间 [i,j]。
基础:Lo(i,i) = Hi(i,i) = xᵢ。
对每个切点 i ≤ k < j,令:
Lmin=Lo(i,k),Lmax=Hi(i,k)
Rmin=Lo(k+1,j),Rmax=Hi(k+1,j)
opₖ = +:候选最小 Lmin+Rmin;候选最大 Lmax+Rmax。
opₖ = −:候选最小 Lmin−Rmax;候选最大 Lmax−Rmin。
opₖ = ×:计算四个积
Lmin×Rmin,Lmin×Rmax,Lmax×Rmin,Lmax×Rmax;
它们的最小、最大分别是该切点的候选。
Lo(i,j) = 所有切点候选中的最小值。
Hi(i,j) = 所有切点候选中的最大值。按长度 j−i+1 递增计算。最终答案 Hi(1,n)。O(n²) 个区间,各尝试 O(n) 个切点、每次常数个运算,时间 O(n³),空间 O(n²)。保存切点及用了哪两个极值状态,即可恢复括号。
固定切点后,左右子表达式独立。加法分别随两边递增;减法随左边递增、随右边递减。乘法对每一边分别是线性函数,因此在两个取值范围构成的矩形上,极值总能在四个角点取得;这些角点由各自可达到的 Lo、Hi 构成,因而确实可行。
任意括号方案都有一个最后运算符,枚举所有切点覆盖全部方案。对子区间长度归纳,同时得到最小值和最大值的正确性。该推导针对 +、−、×;加入除法等操作时,需要重新分析可达值与合法性。
Applications to Graphs
沿用 PPT 的 6.1、6.2、6.3:先在树上由孩子合并到父节点,再沿 DAG 的拓扑顺序传播,最后给一般有向图增加参数来消除状态的循环依赖。
PPT 实际 p77–103Trees
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L44 · 搜索:post-order traversal
先任取一个根 r,定义 Tᵥ 为 v 及其全部后代组成的子树。每个顶点向孩子取答案,再合成为自己子树的答案;叶子是最小子问题,整棵树的答案在根处取得。
同一父亲的孩子子树彼此不重叠,适合独立组合。父节点的整个子树又包含孩子子树;同一个孩子状态可以被父节点的不同候选重复使用。要保存什么信息,取决于父节点怎样与子树连接。
计算顺序:后序 DFS(post-order DFS)
visit(v, parent):
对每个不是 parent 的邻居 u:visit(u, v)
用所有孩子的结果计算 v
叶子先处理,父亲后处理。这段是帮助理解的自写流程,实际题目算法可直接用文字说明后序遍历。在无向树的 DFS 中跳过父节点,才能避免沿同一条边来回走。按深度从深到浅处理也满足依赖。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L44 · 搜索:number of matchings involving the root
Instance: a tree T. Task: count the number of matchings in T.
给定一棵树 T,计算 T 中匹配的总数。
A matching in a graph is a set of edges such that no two of these edges have a vertex in common.
图的一个匹配是一组边,其中任意两条边都没有公共端点。
匹配(matching)是一组互不共享端点的边。它可以为空,也可以只选一条边;本题要数所有匹配,不是只数边数最多的匹配。选定边 v−u 后,两端就都不能再连接其他已选边。
令 children(v) 是 v 的孩子集合。
U(v) = Tᵥ 内 v 没有被匹配的方案数。
M(v) = Tᵥ 内 v 已与一个孩子匹配的方案数。
S(v) = U(v) + M(v) = Tᵥ 的全部匹配数。
叶子:U(v)=1(空匹配),M(v)=0。
整棵树答案:U(r)+M(r)。| 父节点的情况 | 孩子子树如何选 | 怎样组合 |
|---|---|---|
| 不匹配 v | 每个孩子 u 都可任选内部匹配,共 S(u) 种 | 所有孩子都要选,独立相乘 |
| 把 v 与特定孩子 u 匹配 | u 必须内部未匹配,共 U(u) 种;其他孩子 w 仍有 S(w) 种 | 固定 u 时相乘;不同 u 的情况互斥,相加 |
U(v) = ∏[u∈children(v)] (U(u)+M(u))
M(v) = Σ[u∈children(v)] {
U(u) × ∏[w∈children(v), w≠u] (U(w)+M(w))
}教授用 4、3、5 个子树方案说明乘法:三个孩子都要作选择,共 4×3×5=60 种;若指定第二个孩子与 v 相连,只能用其中 2 个内部未匹配方案,就变成 4×2×5=40 种。
任一匹配在 v 处要么不选孩子边,要么恰好选一条 v−u;两类覆盖全部合法情况且互斥。指定 u 后,U(u) 保证 u 不会被重复使用,其他子树的边不可能共享端点。每套子树选择唯一确定一个整体匹配;整体也能唯一拆回相同选择。对子树大小归纳,乘法与加法均无遗漏、无重复。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L44 · 搜索:number of children totaled over all the vertices
沿用课件的五点树:边为 a−b、b−c、b−d、d−e,取 b 为根。后序可以是 a、c、e、d、b。先看具体值,再分析每个孩子关系到底被处理几次。
| 节点 | 孩子 | U:根未匹配 | M:根已匹配 | S:全部 |
|---|---|---|---|---|
| a、c、e | 无 | 1 | 0 | 1 |
| d | e | 1 | 1(选 d−e) | 2 |
| b | a、c、d | 1×1×2=2 | 与 a 配:2;与 c 配:2;与 d 配:1;合计 5 | 7 |
绿色:本步计算或改善的状态;蓝色:相关依赖。演示帮助观察过程,一般正确性由正文证明。
7 个匹配对应:空集;4 个单边集合;{a−b,d−e} 与 {b−c,d−e} 两个双边集合。根取在其他位置,分解方式会变,最后总数仍是 7。
对每个 v,孩子数记为 dᵥ:
1. 用 dᵥ 个因子计算 P,保存 U(v)=P。
2. 对每个孩子 u,加上 U(u) × (P / S(u)),得到 M(v)。
每个点的工作为 O(1+dᵥ)。
Σᵥ dᵥ = n−1,因为除根外,每个节点恰好是一个人的孩子。
总工作 O(n + Σᵥ dᵥ) = O(n)。教授的第二步强调:这里不需要再改算法,只需准确数操作。不能把“某个节点最多有 n−1 个孩子”乘给每个节点。课件 p80 的 O(n³) 是未优化的粗上界;直接重乘的实现用 Σ dᵥ² 可收紧到 O(n²),复用乘积后再按全部孩子关系求和,得到 O(n)。
如果在模数下计数,P/S(u) 不能直接照搬整数除法。可对孩子序列建立前缀积与后缀积,让“除 u 外的积”用两次已存结果相乘得到,仍是每点 O(dᵥ)。这是实现层面的补充,课堂主要展示复用公共乘积与全树求和。
现在目标改为最大化已选边的权重,允许空匹配。重新定义数值状态 F(v)=根 v 在子树内未匹配时的最大权重,G(v)=根已与孩子匹配时的最大权重;它们是权重,不再是前面的方案数。令 B(v)=max(F(v),G(v))。
叶子:F(v)=0,G(v)=−∞(必须匹配却没有孩子,不可行)。
P = Σ[u∈children(v)] B(u)
F(v) = P
G(v) = max[u∈children(v)] [w(v,u)+F(u)+P−B(u)]
答案:max(F(r),G(r))。固定与 v 相配的孩子 u,u 的内部必须未匹配,其他孩子任选最优。不同选择取最大;根未匹配的情况另列。用后序计算并复用总和 P,时间 O(n)、空间 O(n)。负权边可以不选;全负权时空匹配给出答案 0。此题在 PPT 出现,transcript 未展开其解法。
Directed acyclic graphs
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:finish off the rest of dynamic programming
A directed acyclic graph (DAG) is a directed graph with no directed cycles.
DAG 是不存在有向环的有向图。
有向无环图(Directed Acyclic Graph, DAG)没有沿箭头能回到起点的环。忽略方向看起来有一圈,不代表存在有向环;每一步都要服从箭头方向。
拓扑顺序(topological order)把顶点排成一列,让每条边的起点都在终点之前。一个有向图存在拓扑顺序,当且仅当它没有有向环。Kahn 算法或合适的 DFS 实现可以在 O(n+m) 时间找到该顺序,n=|V|、m=|E|。
补录的自动转写把一些 “acyclic” 识别为 “a cyclic”,把算法人名也写错了。本页按 PDF 的定义及上下文统一为 DAG、Kahn、Dijkstra、Bellman–Ford。
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:the sum of all the in degrees
Instance: a DAG G = (V,E) in which each edge e∈E has a weight w(e) (which may be negative), and a source vertex s∈V. Task: for each vertex v∈V, find the smallest weight of a path from s to v.
给定允许负边权的 DAG 和源点 s,求 s 到每个顶点的最小路径权重。
给定源点 s,要算它到每个顶点的最短路径权重。DAG 的边权可以为负:正确顺序由依赖决定,不需要像 Dijkstra 一样依靠非负边权把最小暂定距离定案。
D(t) = s 到 t 的最小路径权重。
D(s)=0;不可达的值为 +∞;空集合的 min 也记为 +∞。
对 t≠s:
D(t) = min[(v,t)∈E] [D(v) + w(v,t)]。
按拓扑顺序计算,最后返回全部 D(t)。正确性:任一到 t 的非空路径都有最后一条边 v→t;最优路径之前的部分也可选成到 v 的最优路径。反过来,每个可达前驱都生成合法路径候选。拓扑顺序保证它们的值已求准,按顺序归纳即可。不可达顶点的全部候选仍为 +∞。
处理 t 的时间 = O(1 + indegree(t))。
Σₜ indegree(t) = m:每条边恰好给终点贡献一次。
加上拓扑排序,总时间 O(n+m),距离与前驱空间 O(n)。实现应按邻接边遍历,避免为每个顶点再扫描所有顶点来寻找前驱。若输入提供出边邻接表,也可按拓扑顺序向外松弛,每条边仍只处理一次。
| 同一 DAG 结构的变式 | 初值 | 合并前驱 |
|---|---|---|
| 最长路径权重 | 源点 0,其余 −∞ | 把 min 改为 max |
| 从 s 到各点的路径条数 | 源点 1(空路径),其余 0 | 对所有前驱的计数求和 |
最长简单路径在一般图里很难,而 DAG 没有环,按拓扑顺序改成 max 就能求解。对路径计数,最后一条边不同对应不同路径,故相加;两种变式仍用 O(n+m) 次基本操作。
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:shortest time to complete the first K
Instance: Two assembly lines, each with n workstations. Task: Find a fastest way to assemble a product using both lines as necessary.
输入两条各有 n 个工作站的流水线及进入、加工、换线、离开时间;求可按需使用两条线的最快装配路线。英文保留该页 Instance 与 Task,具体代价定义见上表。
两条流水线各有 n 道工序。每道只选一条线做,完成第 k 道才能进入第 k+1 道;换线可能花时间。选出总耗时最小的路线。看成图时,每条边都向下一道工序前进,所以天然是分层 DAG。
| 符号 | 含义 |
|---|---|
| aᵢ,ₖ | 在第 i 条线完成第 k 道工序的时间 |
| sᵢ、fᵢ | 从第 i 条线进入、从第 i 条线离开的时间 |
| tᵢ,ₖ | 完成线 i 的工序 k 后,转到另一条线做工序 k+1 的换线时间 |
| F(i,k) | 前 k 道全部完成,且第 k 道在线 i 完成时的最短时间 |
F(1,1)=s₁+a₁,₁;F(2,1)=s₂+a₂,₁。
F(1,k)=a₁,ₖ + min(F(1,k−1), F(2,k−1)+t₂,ₖ₋₁)
F(2,k)=a₂,ₖ + min(F(2,k−1), F(1,k−1)+t₁,ₖ₋₁)
按 k 递增,每轮计算同一工序的两个状态。
答案 min(F(1,n)+f₁, F(2,n)+f₂)。| 自写三工序例子 | 线 1 | 线 2 |
|---|---|---|
| 输入 | s₁=1;a₁=[4,8,3];f₁=1;t₁=[2,2] | s₂=2;a₂=[2,1,7];f₂=2;t₂=[1,3] |
| k=1 | 1+4=5 | 2+2=4 |
| k=2 | 8+min(5,4+1)=13 | 1+min(4,5+2)=5 |
| k=3 | 3+min(13,5+3)=11 | 7+min(5,13+2)=12 |
| 离开 | 11+1=12 | 12+2=14 |
最优为 12:先在线 2 做前两道,再换到线 1 做第三道。每个状态的两种前驱穷尽合法来源,取小值后加当前工序代价,按工序归纳得到最优性。2n 个状态,每个 O(1),总时间 O(n),保存整表 O(n),只求值可保留前一工序的两个值。
课件把这与 Viterbi 的状态转移思想联系起来:按阶段保留“结束在某个状态的最优值”。该联系帮助识别结构,这里无需引入隐马尔可夫模型的细节。
Directed graphs
Single Source Shortest Paths
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:there is a shortest ST path
Instance: a directed weighted graph G = (V,E) with edge weights w(e) which can be negative, but without cycles of negative total weight, and a source vertex s∈V. Task: find the weight of the shortest path from vertex s to every other vertex t.
输入无负权环的有向带权图与源点 s,允许负边权;求 s 到每个顶点的最短路径权重。
For each vertex t, there is a shortest s−t path without cycles.
对每个从 s 可达的顶点 t,都存在一条没有环的最短 s−t 路径。可达性是有限最短路存在的前提。
现在图允许有向环,也允许负边权;课件首先假设没有负权环。拓扑顺序可能不存在,需要为状态再增加一个能递增的参数。关键是:存在一条最短路,不必经过任何环。
若一条 s→t 路线重复经过某个顶点,重复之间形成一个闭合绕行。
没有负环时,可以删掉该绕行而不增加总代价:
正权绕行:删掉后更短;
零权绕行:删掉后同样短。
继续删,得到不重复顶点的最短路。
它最多含 n 个顶点,也就是 n−1 条边。负权环为何有问题?若从 s 能到达该环,且绕环后还能到 t,就能绕任意多圈把总权重不断降低;该 s→t 对没有有限最短距离。课程先排除负环,后面再补充怎样检测。
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:I is going to be the maximum number of edges
B(i,t) = 从 s 到 t、最多使用 i 条边的最小权重。
0 ≤ i ≤ n−1。
基础:B(i,s)=0;当 t≠s 时 B(0,t)=+∞。
对 i>0、t≠s:
B(i,t)=min[(v,t)∈E] [B(i−1,v)+w(v,t)]。
按 i=1,2,…,n−1 逐轮算;同一轮的顶点顺序任意。
答案:每个 t 的 B(n−1,t)。固定最后一条边 v→t,前面的路线至多用 i−1 条边,正是 B(i−1,v)。所有入边都枚举后,合法路线都被覆盖;每个可达候选又确实能接成至多 i 条边的路线。按 i 归纳证明正确,上一节的边数结论把最后一轮接回原题。
复杂度重点:固定一轮,所有目标的候选总数是 Σ indegree(t)=m;最多 n−1 轮,因此松弛工作 O(nm)。完整二维表空间 O(n²),只保留前后两轮可降到 O(n)。
若每轮显式初始化、扫描全部 n 个状态,总代价可写成 O(n(n+m))。课件常用 O(nm) 表达逐边松弛的主项;在 m≥n−1 时两者一致。也可先在 O(n+m) 时间找 s 可达子图,只对这些点运行并把其他点标为 +∞,得到 O(n+m+nᵣmᵣ),其中 nᵣ、mᵣ 是可达部分的点、边数。
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:the predecessor calculation
课件顶点顺序为 s,a,b,c,d。图中的有向边与距离表如下;每一行表示允许的边数上限增加 1。保留正权环没有问题,关键是假设所有环总权重都非负。
绿色:本步计算或改善的状态;蓝色:相关依赖。演示帮助观察过程,一般正确性由正文证明。
| 本轮发生的关键变化 | 路径与代价 |
|---|---|
| i=1:a=6,c=7 | 只能直接从 s 到 a 或 c;b、d 不可达 |
| i=2:b=4,d=2 | s→c→b:7−3=4;s→a→d:6−4=2 |
| i=3:a=2 | s→c→b→a:7−3−2=2 |
| i=4:d=−2 | s→c→b→a→d:7−3−2−4=−2 |
恢复到 d 的最短路径:记录每格获胜的前驱 pred(i,t),从 (4,d) 回到 (3,a)、(2,b)、(1,c)、(0,s),逆转即可得到 s→c→b→a→d。min 是 −2 这个值,arg min / pred 保存的是让它取得该值的选择。
前后两轮足以求距离;若要按每一层回溯,还需要另外保留相应的选择信息。一整轮所有值都不变时可提前停止。课件提到 SPFA 通过选择性处理边减少实际工作,但这些优化的最坏时间仍为 O(nm)。
在完成 n−1 轮后,再检查每条边 u→v:若 D(u) 有限且 D(u)+w(u,v)<D(v),就能判定存在从 s 可达的负环。这个检测对所有终点都检查,包括源点,不沿用距离推导中“源点每轮固定为 0”的例外。
理由:若无可达负环,n−1 条边已经足以达到最优,不应再改善;若有可达负环,环上所有边都不满足改善会导致把不等式沿环相加得到环权非负,与负环矛盾。要检测图中任意位置的负环,可添加到所有顶点的零权超级源点;这属于扩展,不是原题的无负环假设。
All Pairs Shortest Paths
输入时自动保存到当前浏览器。
2026-10-26 21-47-36.-transcript.txt · L2 · 搜索:which vertices we were allowed to see along the way
Instance: a directed weighted graph G = (V,E) with edge weights w(e) which can be negative, but without cycles of negative total weight. Task: for each pair of vertices s,t∈V, find the smallest weight of a path from s to t.
输入允许负边权、没有负权环的有向图,求每一对起点与终点之间的最小路径权重。
全点对最短路径(All Pairs Shortest Paths)要求每个起点到每个终点的距离。仍允许负边、排除负权环。这里按“哪些点可以作为中间点”划分大小,不按边数分层。
先把顶点任意编号 v₁,…,vₙ。
F(i,j,k) = 从 vᵢ 到 vⱼ 的最小路径权重,
中间顶点只允许选自 {v₁,…,vₖ}。
注意:限制的是中间顶点,不限制起点、终点的编号。
允许集合里有哪些点,也不要求全部经过。当新放开 vₖ 时,最优路线只有两类:不经过它,沿用上一轮 F(i,j,k−1);或经过它,把路线切成 i→k 和 k→j。没有负环时,可选择一条不重复顶点的最短路,所以 k 作为中间点至多出现一次。
基础 k=0(不许有中间点):
F(i,i,0)=0。
i≠j 且有直接边时,F(i,j,0)=w(i,j)。
否则 F(i,j,0)=+∞。多条平行边取最小权重。
F(i,j,k)=min(
F(i,j,k−1),
F(i,k,k−1)+F(k,j,k−1)
)。
按 k=1,…,n 递增;每层内 i、j 的顺序任意。
最终返回全部 F(i,j,n)。绿色:本步计算或改善的状态;蓝色:相关依赖。演示帮助观察过程,一般正确性由正文证明。
补充证明:每个最优解可按是否使用中间点 k 分到两类;使用 k 时两段只需前 k−1 个中间点,并可各自取最短。两段若共享其他点,拼起来可能是带重复的路线,但无负环时删去闭合绕行不会变差;因此候选不会制造虚假的更小最优值。结合两个方向和按 k 归纳,递推正确。
O(n³) 个 (i,j,k) 状态,每个比较两个候选,时间 O(n³)。保留所有层需 O(n³) 空间;教授把空间优化标为扩展。只求最终距离时可以用两个 n×n 层,降到 O(n²)。
D 初始化为 k=0 的矩阵。
for k = 1..n:
for i = 1..n:
for j = 1..n:
D[i,j] = min(D[i,j], D[i,k]+D[k,j])在无负环的条件下 D[k,k]=0,当前轮不会降低 D[i,k]、D[k,j],所以原地更新仍使用正确的经 k 候选。k 必须是这个实现的最外层;任意交换成 i、j 在外的单次三重循环,会丢失“已经放开前 k 个中间点”的保证。代码是自写辅助说明。
输入时自动保存到当前浏览器。
COMP3121_COMP9101 Le-transcript.txt · L2 · 搜索:the sub-problem specification
教授贯穿课堂的要求是:先定义状态代表的答案,再说明右边每个候选怎样组成这个答案。下面的索引用来定位前文完整推导;书面算法仍需写出基础情况、递推、顺序、原题答案与复杂度。
| 看到的结构 | 保留的信息 | 保证依赖完成的顺序 | 本页结果 |
|---|---|---|---|
| 两个字符串 | 两个前缀长度 | i、j 递增,或 i+j 递增 | 编辑距离 O(nm) |
| 最后一步切成两段 | 连续区间的两端 | 区间长度递增 | 矩阵链 / 表达式 O(n³) |
| 树上父子连接会占用端点 | 子树 + 根是否在内部匹配 | 孩子先于父亲的后序 | 树匹配计数 O(n) 次基本运算 |
| 图本身无有向环 | 到每个点的最优值 | 拓扑顺序 | DAG 路径 O(n+m) |
| 一般有向图,无负环 | 边数上限 + 终点 | 边数上限递增 | Bellman–Ford 按边求和 O(nm) |
| 所有起终点之间的距离 | 起点、终点、允许中间点的前缀 | 中间点集合逐层扩大 | Floyd–Warshall O(n³) |
要从最优值恢复具体方案,就另外保存一次选择:编辑方向、矩阵切点、树上的匹配孩子、最短路前驱。保存的选择必须与对应状态及其依赖一致,不能只看到一个最小值就推测它来自哪条路径。
课堂与补录各有清晰边界,来源页码和英文检索短语放在对应模块。返回第五周可复习 LCS、背包与基础 DP 状态;本页接续其后的新内容。