LeetCode 887. 雞蛋掉落(DP+二分)

題目鏈接:https://leetcode-cn.com/problems/super-egg-drop/

 

題目大意:

  有K個雞蛋,N層樓。第F層樓及以下雞蛋扔下去不會碎,以上扔下去會碎,如果扔下去沒碎還能繼續用,否則就沒了。問最少多少次能夠保證無論F是哪一層都能測出來。
 

題目思路:

  看了半天沒看出是DP…首先可以發現一個事情,如果只有一個雞蛋,那麼想試只能從一樓慢慢往上了,否則雞蛋碎了就涼了。如果有無數個雞蛋,但是隻有一樓,那麼也當且僅當一次是需要的。這就是dp的預處理。
  接下來咋辦呢?可以這麼考慮DP方程。如果現在有K個雞蛋,N層樓,那麼這個雞蛋可能是從X層樓開始實驗,那麼接下來有兩種情況:

  • 雞蛋碎了。那麼雞蛋變K-1個,但是可以發現F肯定小於X,所以接下來需要測試的樓層數就變成了X-1,那麼接下來需要的次數就是dp[K-1][X-1]
  • 雞蛋沒碎。那麼雞蛋還是K個,但是說明答案是當前或者以上樓層,只需要測試上面的樓層,需要測的數量變N-X,那麼需要的次數就是dp[K][N-X]

  然後就可以根據找個進行DP轉移了,要麼碎了要麼沒碎,因爲要百分百能測出來,所以要取這倆中的最大值,不然大的那種情況發生了咋辦,不就測不出來了麼。但是可以發現,這個X還需要遍歷,複雜度太高了,但是我們還能發現,max(dp[K1][X1],dp[K][NX])max(dp[K-1][X-1],dp[K][N-X])有一個牛逼的性質,那就是隨着x的增大dp[K-1][X-1]非遞減,dp[K][N-X]非遞增,那麼那個交點的位置就是要找的最小值,直接二分找到dp[K][N-X]大於dp[K-1][X-1]的最靠右的位置,因爲我們要的是整數點,但是可能是小數,所以小數兩頭的整數都得試試,也就是試試這個二分出來的點x和這個點+1,取最小值。

  太久沒寫代碼,能力退化的非常嚴重。。(本來就菜),最近狀態也有點不好需要加油了!

 

以下是代碼:

class Solution {
public:
int dp[105][10005];
int superEggDrop(int K, int N) {
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=N;i++)dp[1][i]=i;
    for(int i=1;i<=K;i++)dp[i][1]=1;
    for(int i=2;i<=K;i++){
        for(int j=2;j<=N;j++){
            int l=1,r=j,ans=1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(dp[i][j-mid]>dp[i-1][mid-1]){
                    ans=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            dp[i][j]=1+min(max(dp[i][j-ans],dp[i-1][ans-1]),max(dp[i][j-ans-1],dp[i-1][ans]));
        }
    }
    return dp[K][N];
}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章