877 高楼抛鸡蛋问题
这是一道经典的题目。有多种解决方法,而且题目本身非常抽象,即使case很少也不好理解。例如你基本上很难想明白2个鸡蛋6层楼,需要扔多少次。
这个问题是有最优解的,即对于任意k个鸡蛋,n层,必定存在一种最优方案,使得测试次数达到最少,该方案可以规定每个测试的测试点(解法二可以更好体现这一点)。
这个问题有很多种解,部分解非常精巧但是意义并不是很大。
- 解法一,动态规划,非常直观的一种解法,也非常重要。其中很有意思的就是二分搜索的优化,以及对于max,min的复合优化目标的分析——使用图像。
- 解法二,另一种巧妙的动态规划的定义方法,这种方法比较难理解,但是却能更好的帮助理解这个问题本身。
- 其他不重要的优化,解法一可以使用决策单调性优化为严格的O(KN),解法二可以利用数学知识优化为O(KlogN),但这些都不是重点。
解法一,动态规划
-
dp(k,n)定义为k个鸡蛋,n层楼,最多需要扔的次数
d p ( K , N ) = min 1 ≤ X ≤ N ( max ( d p ( K − 1 , X − 1 ) , d p ( K , N − X ) ) ) \mathrm{dp}(K, N)=\min _{1 \leq X \leq N}(\max (\mathrm{dp}(K-1, X-1), \mathrm{dp}(K, N-X))) dp(K,N)=1≤X≤Nmin(max(dp(K−1,X−1),dp(K,N−X)))
为了确定k个鸡蛋下,n层楼需要多少次,有1-n种选择,从1-n楼抛下鸡蛋,如果碎了,则等于 d p ( K − 1 , X − 1 ) \mathrm{dp}(K-1, X-1) dp(K−1,X−1),鸡蛋减一,层数减一,测试该层以下的层次。如果没碎,则等于 d p ( K , N − X ) \mathrm{dp}(K, N-X) dp(K,N−X),鸡蛋数目不变,测试该层以上的层。由于需要考虑最坏情况,必须保证在某一层抛,取碎或不碎中的大者。这里容易混淆,在保证最坏情况的情形下,选择次数最少的一层,所以最外层是min -
选择,在那一层抛下鸡蛋