一幢 100 層的大樓,給你兩個雞蛋。如果在第 n 層扔下雞蛋,雞蛋不碎,那麼從第 n-1 層扔雞蛋,都不碎。這兩隻雞蛋一模一樣,不碎的話可以扔無數次。最高從哪層樓扔下時雞蛋不會碎?
1. 如果有無數個蛋
如果問題分為兩問,第一問提出如果你鷹蛋有無數個,該如何求解?這個問題比較簡單,只需要二分法就能在o(lgn)的次數內求解問題,問題的第二問是如果只有兩個鷹蛋,該如何求解,我當時的給的答案如下:
2.一種方案,把樓層等分試探求解
把樓層分為x等分,用第一鷹蛋從下往上依次試探乙個範圍,如果第乙個鷹蛋破了,則用另一鷹蛋窮舉。
假如將100層樓分為20等分,則用第乙個鷹蛋分別在第5層,第10層,第15層。。。。依次試探,假如在35層鷹蛋破碎,則用另乙個鷹蛋從31層到34層依次試探,則可以求出破蛋的臨界點。
上面的方法的最壞情況是鷹蛋的臨界點在n-1層(n代表總樓層數),也就是倒數第二層。因為這時候第乙個蛋把所有的等分樓層都嘗試了一遍,而且第二個蛋也要把乙個等分內部的樓層全部嘗試一遍。
假設把總樓層分成了x等份,每個等分內部有n/x個樓層。
在最壞情況下,第乙個蛋需要試探x次,第二蛋則要試探n/x - 1次(即在每個等份內做窮舉),所以最壞情況需要的總次數為x + (n/x) -1。
要獲取最壞情況的最小值,需要對總次數x + (n/x) -1求導數,並取0值,即:
(x + (n/x) -1)'(求導)=1-
(n/x2)
=0求解,可以得到x = sqrt(n)。
在樓層=100的情況下,可以求出使總次數最小的x=10,也就是說如果採用等份的辦法,在樓層總數是100時,10等份是最優情況。
3.最終答案:動態規劃
鷹蛋問題的最優解,可以通過動態規劃的辦法來實現,假設有m樓層,n個鷹蛋,則在第i層試探時會出現兩種狀態,一種狀態是鷹蛋摔破了,則我們下一步只有n-1個鷹蛋,同時總樓層數也縮減為i-1,另一種狀態是鷹蛋沒有摔破,那麼鷹蛋總數不變,還是n個,樓層數則縮減為m-i層。
這樣乙個問題就被分解為兩個規模更小的子問題,通過遞迴的方式求解,遞迴在以下3個狀態結束:1)如果鷹蛋只剩1個,那麼只能對所有的樓層進行窮舉;2)如果樓層是0,則需要試探0次; 3)如果樓層是1,則需要只需要試探1次。
動態規劃的狀態轉移方程如下:
f(m,n)= min};(0 < i < m)
通過方程可以看出,再遞迴的過程中會重複的解子問題,通過array[m][n]來儲存子問題的結果,提高效率,**如下:
[cpp]view plain
copy
const
intnfloor = 100;
const
intnegg = 2;
#define max(a, b) (a) > (b) ? (a) : (b)
intarr[nfloor][negg];
inttest_egg(
intnfloors,
intneggs)
arr[nfloors-1][neggs-1] = min;
return
min;
} int
main(
intargc, _tchar* argv)
動態規劃典型例題解析
動態規劃的主要思想是把問題劃分為乙個個子狀態,乙個狀態的最優解往往是基於其前乙個狀態的最優解。兩個狀態之間的關係,我們就稱之為狀態轉移方程。這裡引出了狀態和狀態轉移方程的概念 狀態是乙個當前的值,這個值是通過前乙個值以及狀態轉移方程推得的。在解決動態規劃問題的時候,我們往往會把問題建模為乙個一維陣列...
動態規劃 合唱團問題解析(二)
題目 有 n 個學生站成一排,每個學生有乙個能力值,牛牛想從這 n 個學生中按照順序選取 k 名學生,要求相鄰兩個學生的位置編號的差不超過 d,使得這 k 個學生的能力值的乘積最大,你能返回最大的乘積嗎?輸入 每個輸入包含 1 個測試用例。每個測試資料的第一行包含乙個整數 n 1 n 50 表示學生...
ACM模組解析之 動態規劃
動態規劃 一.簡介 在acm中,動態規劃是一種將乙個複雜問題分為多個簡單的小問題的思想。在使用動態規劃時,原問題須滿足重疊子問題和最優子結構這個性質。運用動態規劃思想設計的演算法一般比樸素的演算法高效很多。因為在計算某個狀態的時候,已經被計算的子問題將不需要重複計算,而是呼叫之前儲存下的結果。這樣就...