区间动态规划例题:鸡蛋掉落问题(两枚鸡蛋,特定楼层版本)
字数 1548 2025-11-07 12:33:00
区间动态规划例题:鸡蛋掉落问题(两枚鸡蛋,特定楼层版本)
题目描述
你有一栋从 1 到 n 共 n 层的楼和两枚完全相同的鸡蛋。已知存在一个楼层 f(0 ≤ f ≤ n),从任何低于或等于 f 的楼层扔鸡蛋,鸡蛋不会碎;从任何高于 f 的楼层扔鸡蛋,鸡蛋会碎。你需要确定 f 的具体值,且操作需满足以下约束:
- 如果鸡蛋没碎,可以继续使用;
- 如果鸡蛋碎了,就不能再使用;
- 在每次操作中,你可以取一枚鸡蛋从某一楼层扔下,并观察结果。
求最坏情况下需要的最小操作次数。
解题思路
这是一个经典的动态规划问题,但通常用线性 DP 解决。若将其视为区间 DP,可定义状态为:
- dp[i][j] 表示有 i 枚鸡蛋,需要测试 j 层楼时,最坏情况下的最小操作次数。
本题中 i=2,但为了展示区间 DP 思想,我们假设鸡蛋数可扩展(尽管最优解是数学解法)。
状态转移:
- 在第 k 层扔鸡蛋(1 ≤ k ≤ j):
- 如果鸡蛋碎了,说明 f 在 k 层以下,剩余问题为 dp[i-1][k-1](用剩余鸡蛋测 k-1 层)。
- 如果鸡蛋没碎,说明 f 在 k 层以上,剩余问题为 dp[i][j-k](用 i 枚鸡蛋测 j-k 层)。
- 最坏情况下需取两种情况的最大值,再加上本次操作:
\[ dp[i][j] = \min_{1 \le k \le j} \left( \max(dp[i-1][k-1], dp[i][j-k]) + 1 \right) \]
边界条件:
- 如果楼层数为 0(j=0),不需要操作,dp[i][0] = 0。
- 如果鸡蛋数为 1(i=1),只能从低到高逐层测试,dp[1][j] = j。
详细步骤(以 n=10 层,2 枚鸡蛋为例)
-
初始化:
- dp[1][j] = j(仅一枚鸡蛋时,必须线性扫描)。
- dp[i][0] = 0。
-
填表(i=2):
- j=1:dp[2][1] = min(max(dp[1][0], dp[2][0])+1) = max(0,0)+1 = 1。
- j=2:
- k=1:max(dp[1][0], dp[2][1])+1 = max(0,1)+1=2
- k=2:max(dp[1][1], dp[2][0])+1 = max(1,0)+1=2
- 取最小值 2。
- j=3:
- k=1:max(0, dp[2][2])+1 = 0+2+1? 需计算:实际是 max(0,2)+1=3
- k=2:max(dp[1][1], dp[2][1])+1 = max(1,1)+1=3
- k=3:max(dp[1][2], 0)+1 = max(2,0)+1=3
- 最小值为 3。
- 继续计算至 j=10。
-
优化:
实际计算中发现,当 i=2 时,dp[2][j] 的解是满足 t(t+1)/2 ≥ j 的最小 t。例如 j=10,t=4 因为 4×5/2=10≥10,所以 dp[2][10]=4。
答案验证(n=10)
- 策略:第一次在 4 层扔:
- 若碎,剩 1 枚鸡蛋测 1~3 层(最多 3 次,总 4 次)。
- 若不碎,第二次在 4+3=7 层扔:
- 若碎,剩 1 枚鸡蛋测 5~6 层(最多 2 次,总 4 次)。
- 若不碎,第三次在 7+2=9 层扔,依此类推。
- 最坏情况下操作次数为 4,与 DP 结果一致。
关键点
- 区间 DP 通过枚举第一次扔鸡蛋的楼层 k,将问题划分为两个子区间。
- 当鸡蛋数为 2 时,可用数学公式简化,但 DP 思路适用于更多鸡蛋的情况(如 i>2)。
- 状态定义中“区间”是楼层范围,决策是选择划分点 k。