动态规划:青蛙跳台阶
一只青蛙要跳上有 n 级的台阶,每次只能跳 1 级或 2 级台阶,问青蛙总共有多少种不同的跳法?
加法原理
若完成一件事有多种 “互不重叠的路径”,则总方法数 = 各路径方法数之和。
在青蛙跳台阶问题中,加法原理的应用核心是 ——从 “最后一步的跳法” 倒推总跳法:
要跳到第 n 级台阶,青蛙的最后一步只有两种可能(因为每次只能跳 1 级或 2 级),且这两种可能完全独立、无重叠:
- 最后一步跳 1 级:说明青蛙在跳这 1 级之前,已经跳到了第 n-1 级台阶。此时,跳到第 n 级的方法数 = 跳到第 n-1 级的方法数(因为最后一步固定跳 1 级,不增加新的方法),即 f(n-1);
- 最后一步跳 2 级:说明青蛙在跳这 2 级之前,已经跳到了第 n-2 级台阶。此时,跳到第 n 级的方法数 = 跳到第 n-2 级的方法数(最后一步固定跳 2 级),即 f(n-2)。
由于这两种路径覆盖了所有跳到第 n 级的可能(没有其他跳法),根据加法原理,总跳法数为两者之和:f(n) = f(n-1) + f(n-2)
跳到n-1层的跳法难道不会覆盖n-2层的跳法,难道不会有重合吗,怎么就是完全独立无重叠呢
集合划分保证无重叠
以 “最后一步的跳法” 划分集合
核心逻辑:无论前面怎么跳,最后一步只能是 “跳 1 级” 或 “跳 2 级”,因此总跳法 =“最后一步跳 1 级的方案数”+“最后一步跳 2 级的方案数”。
子集合 A(最后一步跳 1 级):说明跳到第 5 级前,已先到第 4 级,对应 “跳到第 4 级的所有跳法”(共 f (4)=5 种):
- 1->2->3->4->5(最后 1 级:4→5)
- 1->2->4->5(最后 1 级:4→5)
- 1->3->4->5(最后 1 级:4→5)
- 2->3->4->5(最后 1 级:4→5)
- 2->4->5(最后 1 级:4→5)
子集合 B(最后一步跳 2 级):说明跳到第 5 级前,已先到第 3 级,对应 “跳到第 3 级的所有跳法”(共 f (3)=3 种):
- 1->2->3->5(最后 2 级:3→5)
- 1->3->5(最后 2 级:3→5)
- 2->3->5(最后 2 级:3→5)
总之要想跳到第5阶,那么一定是从第3阶或者第4阶过来的,方案数也就是这两种集合方案数的和。我不知道跳到第4的阶的方案是什么,也不知道跳到第3阶的方案是什么,但是按照第3阶和第4阶,我可以将跳到第5阶所有的方案分成不重合的两个集合,只要求出这两个集合的方案数,然后相加就是最后的方案数。
这两个集合把所有的方案不重不漏的划分开来,符合无重叠性和完全覆盖性。第一个集合的所有方案,最后一步必然经过第4阶台阶,第二个集合的所有方案,最后一步必然经过第3阶台阶。
集合的唯一划分标准
这里有一个困惑,集合一中不是也会有方案经过3吗,为什么不会与集合二重叠呢?
两个集合的划分标准是 “最后一步的来源”,而非 “方案是否经过某个中间台阶”,因此即使集合一的方案经过 3 阶,也不会与集合二重叠
- 集合一(来自 n-1 阶):所有方案的最后一步是 “从第 4 阶跳 1 阶到第 5 阶”(无论这个方案在到达 4 阶之前,是否经过 3 阶、2 阶等)。
例:方案 “1→2→3→4→5”,最后一步是 “4→5”,属于集合一;哪怕方案是 “1→3→4→5”,最后一步仍是 “4→5”,也属于集合一。 - 集合二(来自 n-2 阶):所有方案的最后一步是 “从第 3 阶跳 2 阶到第 5 阶”(无论这个方案在到达 3 阶之前,是否经过 2 阶、1 阶等)。
例:方案 “1→2→3→5”,最后一步是 “3→5”,属于集合二;哪怕方案是 “1→3→5”,最后一步仍是 “3→5”,也属于集合二。
一个方案的 “最后一步” 是唯一的、不可拆分的,这是避免重叠的核心:
- 集合一的方案,无论中间是否经过 3 阶,其 “最后一步” 必然是 “4→5”(跳 1 阶);
- 集合二的方案,无论中间是否经过其他台阶,其 “最后一步” 必然是 “3→5”(跳 2 阶)。
这就像 “无论你之前走了哪条路,最后一步是‘迈左脚进门’还是‘迈右脚进门’,是完全不同的两个动作”—— 不会存在一个方案,“最后一步既从 4 阶跳 1 阶,又从 3 阶跳 2 阶”,因此两个集合绝对无重叠。
其他划分集合方式
“是否以 1 级跳开头”?
- 集合 1:第一步跳 1 级(所有路径均以 “1->…” 开头);
- 集合 2:第一步跳 2 级(所有路径均以 “2->…” 开头)。
由于青蛙每次只能跳 1 级或 2 级,第一步只有 “跳 1 级” 或 “跳 2 级” 两种可能(没有其他选择),因此这两个集合完全满足 “互不重叠、覆盖全部” 的加法原理前提 —— 总跳法数 = 集合 1 的方案数 + 集合 2 的方案数。
第一步跳 1 级(集合 1,对应 “先到第 1 级,再跳剩余 4 级”)
剩余 4 级的跳法数为 f (4)=5 种,因此集合 1 应有 5 种方案:
- 1->2->3->4->5(1+1+1+1)
- 1->2->3->5(1+1+2)
- 1->2->4->5(1+2+1)
- 1->3->4->5(2+1+1)
- 1->3->5(2+2)
第一步跳 2 级(集合 2,对应 “先到第 2 级,再跳剩余 3 级”)
剩余 3 级的跳法数为 f (3)=3 种,你的列表完全正确,共 3 种方案:
- 2->3->4->5(1+1+1)
- 2->3->5(1+2)
- 2->4->5(2+1)
以 “是否包含 2 级跳” 划分(按跳法的 “组成结构” 分类)
核心逻辑:跳法的本质是 “1 级跳(记为 a)” 和 “2 级跳(记为 b)” 的组合,满足 “a + 2b = 5”(总台阶数为 5),因此先确定 b 的可能取值,再按 b 的数量分类:
子集合 C(b=0,全是 1 级跳):只有 1 种(5 个 1 级跳):1->2->3->4->5
子集合 D(b=1,1 个 2 级跳 + 3 个 1 级跳):2 级跳的位置有 4 种(插空法:在 4 个 “间隔” 中选 1 个放 2 级跳):
- 1->(2 级:2→4)->5(1+2+1+1)→ 1->2->4->5
- (2 级:1→3)->4->5(2+1+1+1)→ 1->3->4->5
- 1->2->(2 级:3→5)(1+1+2+1)→ 1->2->3->5
- 2->(2 级:3→5)(1+2+1)→ 2->3->5(注意:这里 b=1,2 级跳是 3→5,前面是 1 级跳 2→3)
子集合 E(b=2,2 个 2 级跳 + 1 个 1 级跳):2 个 2 级跳的位置有 3 种(插空法:在 3 个 “间隔” 中选 2 个放 2 级跳):
- (2 级:1→3)->(2 级:3→5)(2+2+1)→ 1->3->5
- 2->(2 级:2→4)->5(1+2+1)→ 2->4->5
- 2->3->(2 级:3→5)(1+1+2)→ 2->3->5