丢棋子问题(鹰蛋问题)
Last updated
Last updated
问题简述
思路1
定义 dp(k, n)
表示 k 个棋子扔 n 层最坏情况下需要的最少次数;
初始化有 dp(0, n) = dp(k, 0) = 0, dp(1, n) = n, dp(k, 1) = 1
;
为什么要初始化
k
或n
为0
的情况?
递推公式: dp(k, n) = 1 + min{max{dp(k-1, t-1), dp(k, n-t)}}, 1 <= t <= n
;
假设在第
t
层扔下,有两种可能:如果碎了,则继续用k-1
个蛋在t-1
层楼尝试;如果没碎,则继续用k
个蛋在n-t
层楼尝试,取其中较大值作为最差情况,即max{dp(k-1, t-1), dp(k, n-t)}
;而t
可以取[1, n]
,取其中最小值作为最少次数;+1
表示当前层扔了 1 次;
直接使用上述方法会超时,可以利用二分或决策单调性(四边形法则)优化复杂度:
思路2:反向思维(推荐)
定义 dp(i, j)
表示 i 个棋子扔 j 次最多能确定的层数;
类似 01 背包 的两种尝试方法:1)固定重量需要的最小空间,2)固定空间能放的最大重量
初始化 dp(0, j) = dp(i, 0) = 0, dp(1, j) = j, dp(i, 1) = 1
;
递推公式:dp(i, j) = 1 + dp(i - 1, j - 1) + dp(i, j - 1)
;
如果棋子碎了,对应
r1 := dp(i-1,j-1)
,说明这一层的下方可以有r1
层; 如果棋子没碎,对应r2 := dp(i,j-1)
,说明这一层的上方可以有r2
层;+1
表示当前回合确定了 1 层;