1. 程式人生 > 其它 >經典動規雞蛋掉落問題

經典動規雞蛋掉落問題

最近在複習動態規劃,然後就想看一下自己的成果,就去力扣翻了下這道題。比較經典
貼個力扣連結:https://leetcode-cn.com/problems/super-egg-drop/
還記得剛開始看的時候,看的一知半解,現在又看這道題,來寫一下自己的思路和心得
首先,讀題,我個人傾向於讀完題,然後去看例項加深一下理解。當只有一個雞蛋的時候,那要試出來肯定得一層一層爬,然後最差的情況就是,爬到了頂樓雞蛋才碎,或者沒碎。所以n層樓一個雞蛋,最少需要n次,這是毫無疑問的。
然後就是兩個蛋的情況了,這個時候我有兩個蛋,我可以在中間找個樓層去扔,如果運氣差,碎了,那我就只有一個蛋了,唉,這是不是可以迴歸到一個蛋的情況,比方說我在m層扔碎了,那麼我還需要m-1次,總共加起來是m次吧。然後思考一下,我有兩個蛋的時候,我經歷了什麼,先扔碎一個蛋,把問題簡化為一個蛋,巧了,這不正好可以用到動規麼。dp[k][m]表示k個蛋在m層需要的次數。比方說這個例子裡,我在m層扔了蛋,碎掉了,我去取dp[1][m-1] = m-1;是吧,那麼dp[2][n] = dp[1][m-1]+1;
不過這個表示式還是有問題,裡面還有m和n,我們需要找到mn的對應關係,不能亂扔是吧,比方說我在五樓扔蛋和九樓扔蛋,結果就不一樣。
我一開始想的比較複雜,想求出這個分割點,然後每次去取,如果求出來了,執行速度估計還是很快的,但是這很不演算法。我覺得寫演算法的人是不要參與這種複雜的腦力的,它只需要讓電腦去機械的執行出答案來好了。然後發現,如果我在m層蛋沒碎,那麼問題是不是可以看成兩個蛋,m-n層需要多少次呢。
好,現在解法很明顯了,中間選個點,分情況討論。

  • 蛋碎了,需要dp[k-1][m]次
  • 蛋沒碎,需要dp[k][n-m]次
    初步想法就是,在這裡遍歷,便利出最短的次數,給dp[k][n]賦值。
    程式碼實現如下
    public int superEggDrop(int k, int n) { if(k==1){ return n; } int[][] dp = new int[k+1][n+1]; for(int i=1;i<n+1;i++){ dp[1][i] = i; } for(int i=2;i<k+1;i++){ for(int j=1;j<n+1;j++){ int min = dp[i-1][j]; for(int l=2;l<j;l++){ min = Math.min(min, Math.max(dp[i-1][l-1]+1, dp[i][j-l]+1)); } dp[i][j] = min; } } return dp[k][n]; }

    這裡三重迴圈,拿去力扣跑一下,果然超時了。明天再優化一下