区间动态规划例题:鸡蛋掉落问题(K个鸡蛋,N层楼版本)
字数 1735 2025-11-20 09:43:57
区间动态规划例题:鸡蛋掉落问题(K个鸡蛋,N层楼版本)
问题描述
你手中有K个完全相同的鸡蛋,并有一座N层高的建筑。已知存在一个楼层F(0 <= F <= N),从任何高于F的楼层扔下鸡蛋,鸡蛋都会破碎;从F层或比F低的楼层扔下鸡蛋,鸡蛋不会破碎。每次操作,你可以取一个鸡蛋从某一层楼扔下:
- 如果鸡蛋没碎,可以继续使用这个鸡蛋
- 如果鸡蛋碎了,这个鸡蛋就不能再用了
你的目标是确定F的最小值(即鸡蛋刚好不会破碎的最高楼层)。请计算在最坏情况下,你最少需要扔多少次鸡蛋才能确定F的值。
解题思路分析
这是一个经典的区间动态规划问题。我们需要考虑在不同楼层区间和不同鸡蛋数量下的最优策略,找到最坏情况下的最小尝试次数。
动态规划定义
定义dp[k][n]表示有k个鸡蛋,需要测试n层楼时,在最坏情况下需要的最少尝试次数。
状态转移方程推导
- 当k=1时(只有一个鸡蛋):只能从低到高逐层测试,最坏情况需要n次尝试
- 当n=0时:不需要测试,次数为0
- 当n=1时:只需要测试1次
对于一般情况dp[k][n]:
- 我们可以选择在第i层(1≤i≤n)扔第一个鸡蛋
- 如果鸡蛋碎了:那么F在[1, i-1]层,剩下k-1个鸡蛋,需要dp[k-1][i-1]次
- 如果鸡蛋没碎:那么F在[i, n]层,剩下k个鸡蛋,需要dp[k][n-i]次
- 最坏情况下取两者最大值,再加1(当前这次尝试)
因此状态转移方程为:
dp[k][n] = min{1 + max(dp[k-1][i-1], dp[k][n-i])},其中i从1到n
具体计算步骤
以K=2, N=6为例:
-
初始化:
- dp[1][0] = 0, dp[1][1] = 1, dp[1][2] = 2, ..., dp[1][6] = 6
- dp[k][0] = 0 (k≥1)
- dp[k][1] = 1 (k≥1)
-
计算dp[2][1] = 1
-
计算dp[2][2]:
- i=1: 1 + max(dp[1][0], dp[2][1]) = 1 + max(0,1) = 2
- i=2: 1 + max(dp[1][1], dp[2][0]) = 1 + max(1,0) = 2
- 取最小值:dp[2][2] = 2
-
计算dp[2][3]:
- i=1: 1 + max(0, dp[2][2]) = 1 + 2 = 3
- i=2: 1 + max(1, dp[2][1]) = 1 + 1 = 2
- i=3: 1 + max(2, 0) = 3
- 取最小值:dp[2][3] = 2
-
计算dp[2][4]:
- i=1: 1 + max(0,3) = 4
- i=2: 1 + max(1,2) = 3
- i=3: 1 + max(2,1) = 3
- i=4: 1 + max(3,0) = 4
- 取最小值:dp[2][4] = 3
-
计算dp[2][5]:
- i=1: 1 + max(0,4) = 5
- i=2: 1 + max(1,3) = 4
- i=3: 1 + max(2,2) = 3
- i=4: 1 + max(3,1) = 4
- i=5: 1 + max(4,0) = 5
- 取最小值:dp[2][5] = 3
-
计算dp[2][6]:
- i=1: 1 + max(0,5) = 6
- i=2: 1 + max(1,4) = 5
- i=3: 1 + max(2,3) = 4
- i=4: 1 + max(3,2) = 4
- i=5: 1 + max(4,1) = 5
- i=6: 1 + max(5,0) = 6
- 取最小值:dp[2][6] = 4
算法优化
直接实现的时间复杂度是O(KN²),可以通过二分搜索优化到O(KNlogN)。观察发现dp[k-1][i-1]随i单调递增,dp[k][n-i]随i单调递减,可以在i的取值范围内使用二分查找找到使两者最接近的点。
最终结果
对于K=2, N=6的情况,最少需要4次尝试就能在最坏情况下确定鸡蛋刚好不会破碎的最高楼层。