題目是這樣:你面前有一棟從 1 到n共n層的樓,然後給你k個雞蛋(k至少為 1)。現在確定這棟樓存在樓層0 <= f <= n,在這層樓將雞蛋扔下去,雞蛋恰好沒摔碎(高於f的樓層都會碎,低於f的樓層都不會碎)。現在問你,最壞情況下,你至少要扔幾次雞蛋,才能確定這個樓層f呢?
首先我們來看一下,什麼叫做最壞情況下,至少要仍幾次雞蛋,才能確定這個樓層f?
我們來舉個簡單的例子,當雞蛋為1個時,如何確定這個樓層f,這時只能從第一層開始向上嘗試,當第一層沒有碎時,就繼續在第二層嘗試,。。。。。。,當在第k層嘗試時,雞蛋碎了(那麼說明n-1層已經嘗試過了且沒有碎),所以說我們需要扔k次才能確定樓層。但這個k最壞情況下是多少尼?肯定是一直扔到最高層才碎,此時k=n吧。
那麼當有k個雞蛋,n層樓時該如何做尼?
我們先來分析一下可不可以用動態規劃來解決。
1、找dp含義
dp[k][i]表示當有k個雞蛋,i層樓時,最壞情況下需要扔雞蛋的次數才能確定樓層f
2、找轉移狀態當在第i層樓扔雞蛋時,有兩種結果(碎了或沒碎)。
當沒碎的話,我們有k個雞蛋,但此時,我們需要從i+1 - n層繼續嘗試,找到樓層f,那麼此時的問題是你面前有一棟n-i層的樓,然後給你k個雞蛋(k至少為 1)。現在確定這棟樓存在樓層0 <= f <= n,在這層樓將雞蛋扔下去,雞蛋恰好沒摔碎(高於f的樓層都會碎,低於f的樓層都不會碎)。現在問你,最壞情況下,你至少要扔幾次雞蛋,才能確定這個樓層f呢?**
此時,轉移狀態就為 dp[k][i]=max(dp[k][n-i],dp[k-1][i-1])+1 //最壞情況下,子問題嘗試的次數還要加上本次嘗試的一次。
3、找結束條件
當i=0時,也就是樓層沒有高度,此時我們也就不用嘗試了,直接返回0;
當k=1時,也就是我們有1個雞蛋,那我們就只能從第一層開始嘗試,最壞情況下需要嘗試到頂層,也就是返回樓層的高度i;
有了轉移方程和結束條件,那麼**就可以寫出來了。
#include
#include
using
namespace std;
int memo[
500]
[500]=
;intdp(
int k,
int n)
return ans;
}int
main()
非遞迴實現
#include
#include
using
namespace std;
int dp[
500]
[500]=
;int
fun(
int k,
int n)
for(
int i =
1; i <= n; i++
)for
(int i =
2; i <= k; i++)}
dp[i]
[j]= res;}}
return dp[k]
[n];
}int
main()
每日一題 高樓扔雞蛋
2020.04.11 這題其實正常思路還可以,有點類似b站李永樂老師講的方法。核心還是尋找子問題,dp i j 表示一共有i層j個雞蛋。可以把dp i j 分為先在第m層扔一次,在剩下的結果裡繼續分析。dp i j min dp i j max dp m j 1 dp n m j 第乙個min對應最...
每日一道演算法題
no.1 設指標變數fron t表示鏈式佇列的隊頭指標,指標變數rear表示鏈式佇列的隊尾指標,指標變數s指向將要入佇列的結點x,則入佇列的操作序列為 a.front next s front s b.s next rear rear s crear next s rear s d.s next f...
每日一道演算法題
no.1 若有 18 個元素的有序表存放在一維陣列 a 19 中,第乙個元素放 a 1 中,現進行二分查詢,則查詢 a 3 的比較序列的下標依次為 a.1,2,3 b.9,5,2,3 c.9,5,3 d.9,4,2,3 答案 d.第一次查詢,隊首為下標1,隊尾下標18,所以是 1 18 2 9 第二...