1、問題描述
有層樓,個雞蛋,雞蛋是相同的,臨界樓層是指從某個樓層之上拋下來,都會碎,但從這個樓層之下拋下來,都不會碎。沒有碎的雞蛋可以重複使用。試假設能找到這個臨界樓層需要拋投的最少次數。
2、背景與原理
看李永樂的視頻:https://www.bilibili.com/video/av96214853
設爲在從層樓,個蛋的情況下需要拋投的最少次數,情況有多少種呢。當然是t種,從每一層都拋出一個雞蛋試一下。
現在就要得到這t個拋投實驗中的最小拋投次數。設爲從層樓拋下1個雞蛋進行測試而得到的拋投數。這t種拋投有通用的遞推模式:
假設在k層樓進行拋投,會產生兩種情況:
碎了:問題規模變爲:
沒碎:問題規模變爲:
所以有:
,也就是求出這種情況下最大的拋投次數。
而
可以用一個數學公式表示:
3、爲什麼可以遞歸求解呢
這裏是我自己的想法,覺得不對的可以留言指正。
首先來看上面的數學公式,由和來決定,而且一旦決定了,那麼就可以由和這兩列的數來確定,具體是由這兩列的那些數來決定依賴k的值。然後又有:
1.當時,總是有,
2.當時,總是有,
所以可以得到的兩條邊界值。如下圖所示。
可以根據紅色圈的數求出藍色圈的值,然後按列一個個求取,就可以把其他位置的值都求出來。就是根據列和列層以上的值求出層列的值。
4、python代碼
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import numpy as np
def my_max(num1, num2):
if (num1 >= num2) :
max_num = num1
else:
max_num = num2
return max_num
def init_array(floors, eggs):
array = [[0 for i in range(eggs)] for i in range(floors)]
array = np.array(array)
array[0,:] = 1
for i in range(floors):
array[i,0] = i+1
return array
def get_array(floors, eggs):
array = init_array(floors,eggs)
print(array)
print("-----------------------------")
for e in range(1,eggs):
for f in range (1,floors):
temp_m = [[0 for i in range(1)] for i in range(f)]
temp_m = np.array(temp_m)
for k in range (f):
m1 = array[k,e-1]
m2 = array[(f-k-2),e]
temp_m[k-1,0] = my_max(m1,m2)+1
array[f,e] = min(temp_m[:,0])
return array
def get_result(floors, eggs):
array = get_array(floors,eggs)
result = array[floors-1,eggs-1]
print(array)
print("---------------------------------")
return result
if __name__ == '__main__':
test = get_result(16,10)
print("result =",test)