测鸡蛋摔碎楼层的最少次数:动态规划
问题描述
有n个鸡蛋,和一栋m层高的楼,欲测量鸡蛋最高从第几层楼摔下不会摔碎,问最小的测量次数
约定:假设鸡蛋极限耐受楼层是x,那么从 1 ~ x 层摔下,不会碎,从 x+1 ~ m 层摔下,碎
样例
样例输入1:
2 100
样例输出1:
14
样例输入2:
3 1000
样例输出2:
19
思路
这题动态规划。。。挺难想的
约定:
未知结果的楼层:在这一层摔下鸡蛋,不知道是碎还是不碎的楼层
已知结果的楼层:在这一层摔下鸡蛋,有唯一确定的已知结果
(如果在x层摔鸡蛋,没碎,那么1~x层的结果都是已知的,即:鸡蛋不会碎)
(如果在x层摔鸡蛋,碎了,那么x~m层的结果都是已知的,即:鸡蛋碎)
未知结果的楼层有10层,不是说从1 ~ 10楼未知,10表示一个数目,不是区间,10层未知,可以是20 ~ 30层楼,或是114~124层 … 但是我们不关心在第几层,我们关心的问题是有几层楼的结果是未知的
对于未知的x层楼,不管是在10 ~ 10+x 还是 30 ~ 30+x,我们测量的策略是不会变的,所以楼层在哪不重要,关键是剩余多少未知的楼层
假设现在有j
层楼的结果是未知的,手中有i
个鸡蛋,在第k
层试摔一个鸡蛋,有两种可能:碎/不碎
-
如果碎了,说明
k
层以及往上的楼层,共j-k
层楼,都会摔碎鸡蛋,结果是已知的,未知结果的楼层是剩下的前k-1
层楼,那么问题转换为:
【用手中的 i-1 个鸡蛋,测量未知结果的 k-1 层楼】的次数 -
如果没碎,说明
k
层以及往下的楼层,共k
层楼,不会摔碎鸡蛋,结果是已知的,未知结果的楼层是剩下的后j-k
层楼,问题转换为:
【用手中的 i 个鸡蛋,测量未知结果的 j-k 层楼】的次数
因为在第k层楼测了一次,又因为要保证测出结果(或者说运气最坏的情况下),应该取情况1,2中最大的数值+1,就是【手里有i个鸡蛋,未知结果的楼层数目是j,在第k层未知结果的楼层测量】的答案
实际情况是这样的:
我们不一定只能在第k个未知结果的楼层上做上述测量,我们可以从第一,第二 … 一直到最后一层未知结果的楼层,都做一次测量
将k取遍1~j ,找到最小的结果,作为问题【手里有 i 个鸡蛋,未知结果的楼层数目是 j,求最小测量次数】的答案
于是自然地 写出状态转移方程
// dp[i][j]表示用i个样本,测量结果未知的j层楼,最少次数
int dp[MAXLEN][MAXLEN];
// 手中i个鸡蛋,未确定结果的楼层有j层,在哪一层起手开始测试呢?
// k遍