扔雞蛋
阿新 • • 發佈:2018-08-17
() max 比較 兩種 一件事 memset cpp 雞蛋 open
Description
Jzj要來做一個經典的實驗:測試雞蛋殼的堅硬程度。
Jzj正好處於N層高的摩天大樓中,所以通過從某一樓層向下扔雞蛋來測試雞蛋殼的堅硬程度。
Jzj有M個雞蛋,所有的雞蛋硬度都一樣。如果雞蛋從第L層摔下去沒有碎,而在L+1層摔碎了,那麽稱雞蛋的硬度是L。嗯,反正jzj不喜歡吃雞蛋,所以不用擔心浪費的問題。大樓共有N層高,如果在N層還沒有摔碎,就認為硬度是N;如果在第1層就碎了,硬度為0。
雖然jzj不喜歡吃雞蛋,但是jzj的好朋友yk特別喜歡吃雞蛋。為了幫好朋友保護可憐的小雞蛋,jzj想知道用這麽多雞蛋,最少摔幾次就可以保證測試出它們的硬度。
Analysis
一開始想到了二分,每次都選擇樓層中間扔,啪嘰碎掉之後長度縮減一半,直到只剩一個雞蛋每層試扔一次。
但是我忽視了一個問題。首先明白一件事情,對於高度大於1的樓層,雞蛋越多越好。那麽在這個前提下探究這個問題,如果在低於中間部分的樓層扔雞蛋,有兩種情況,碎和不碎。
- 如果不碎,那麽多一個雞蛋探索更多的樓層也未嘗不會更優
- 如果碎了,那麽碎掉一個雞蛋卻可以只用探究更少的樓層
那麽低樓層絕對存在優於中間樓層的情況,而高樓層無需分析,理由同上。
所以只能采用動態規劃了,因為不具有有序性無法二分所以對於i層樓只能枚舉1到i/2層樓,尋找max(dp[j-1][k-1],dp[i-j][k])的最小值即可。
為了方便,遞歸比較好寫。
Code
#include <bits/stdc++.h> int m,n,dp[1010][1010]; int search(int h,int e){ if(e==1)return dp[h][e]=h; if(!h)return 0; if(dp[h][e]<0x3f3f3f3f)return dp[h][e]; for(int i=1;i<=h/2+1;i++) dp[h][e]=std::min(dp[h][e],std::max(search(i-1,e-1),search(h-i,e))+1); return dp[h][e]; } int main(){ freopen("eggs.in","r",stdin); freopen("eggs.out","w",stdout); std::cin>>m>>n; memset(dp,0x3f3f3f3f,sizeof(dp)); std::cout<<search(n,m)<<std::endl; return 0; }
扔雞蛋