python实现李永乐老师的双蛋问题
https://www.bilibili.com/video/av96214853
一个鸡蛋从高楼扔下,在低楼层不会摔碎,高楼层会摔碎,假设楼共100层,找出临界的楼层,即到这一层鸡蛋正好摔碎,最少要多少次
如果只有1个蛋,那么就只能从第一层扔,碎了就是1,没有到第二楼继续扔,最少要扔100次
如果有两个蛋,就先用第一个蛋确定范围,再用第二个蛋一层层测试
将100层拆分成10次,10,20…,100 ,最多10次,即90-100,之后再用另一个蛋最多扔9次 [1,9] ,最少要扔19次
优化下,最开始扔n层,之后n-1层,之后n-2层……,最后扔1层,这样,每一层扔的次数都一样是n+1,
计算n的值:n+(n-1)+……+1=100,等差数列,(1+n)*n/2=100,n^2+n=200,n^2+n+1/4=200.25,n=(200.25)^(1/2)-0.5=13.65,n取14
14,27,39,50,60,69,77,84,90,95,99,100 ,最多扔了12次,那最少要扔14次,
问题拓展,假如我有n个蛋,楼总共有t层楼,计算出最少要扔多少次 记为M
式子为:M=fun(n,t),
1.当n为1时,总是有M=t,
2.当t=1时,总是有M=1,
也就是问题至少要是2个蛋,楼有两层,即fun(2,2),才开始计算。
先扔第一个鸡蛋,在第k层扔,1<=k<=t;
两种结果,1、碎,临界楼层在1到k层,下一次扔fun(n-1,k),之中。
2、不碎,临界楼层在上面,fun(n,t-k),之中,
取两者的最大值,max{ fun(n-1,k-1) , fun(n,t-k) } + 1
k需要从第1层,一直第t层,这样找出最小的 max{ fun(n-1,k-1) , fun(n,t-k) } + 1 的值,
作为f(n,t)的值
fun(2,2)=min{ fun(2,1) , fun(1,2) } + 1 ; #因为要比上一种多扔最后一次。
--按照李永乐老师的递归思想,程序开销很大,楼层越高开销越大,之后改成循环做处理
式子为:M=fun(n,t),
1.当n为1时,总是有M=t,
2.当t=1时,总是有M=1,
def fun_recursion(v_floors, v_eggs):
if v_eggs == 1:
return v_floors
if v_floors == 1:
return 1
if v_eggs == 0 or v_floors == 0:
return 0;
v_min = 1000000;
for i in range(1, v_floors + 1):
result_1 = fun_recursion(i - 1, v_eggs - 1) + 1;
result_2 = fun_recursion(v_floors - i, v_eggs) + 1;
v_min = min(v_min, max(result_1, result_2));
return v_min
# 循环 动态规划思想,全局最优解包含局部最优解,由局部最优解拓展到全局最优解
# 先建立二维列表保存结果数据,将只有1个鸡蛋和只有1层楼的情况填写到列表中, 之后再有局部解推出全局解
def fun_cycle(v_floors, v_eggs): # 5 2
list_2d = [[0 for col in range(v_eggs)] for row in range(v_floors)] # 用于保存局部解存放楼层和鸡蛋的值,第一维度为楼层数,第二维度为鸡蛋数
# list_2d[v_floors][v_eggs]
for m in range(v_floors): # 只有1个鸡蛋时
list_2d[m][0] = m + 1;
for m in range(v_eggs): # 只有1层楼时
list_2d[0][m] = 1;
# 从两个蛋,两层楼 逐步开始求解
for v_floor in range(1, v_floors):
for v_egg in range(1, v_eggs):
# k记录第一个蛋扔的层数,从第二层开始扔
v_min = 1000000;
for k in range(1, v_floor + 1):
result_1 = list_2d[k - 1][v_egg - 1] # 蛋碎了,临界楼层应该在k-1
result_2 = list_2d[v_floor - k - 1][v_egg] # 蛋没碎,临界楼层应该在j-k
v_max = max(result_1, result_2) + 1
v_min = min(v_min, v_max)
list_2d[v_floor][v_egg] = v_min
# 打印循环结果
for i in range(v_floors):
print(list_2d[i])
return list_2d[v_floors - 1][v_eggs - 1]
# 打印递归结果
for i in range(1, 20):
for j in range(1, 10):
print(fun_recursion(i, j), end=' ')
print('')
# print(fun_cycle(20, 10))
# print(fun_recursion(2, 3))