LeetCode 887 雞蛋掉落 (決策單調性)

你將獲得 K 個雞蛋,並可以使用一棟從 1 到 N 共有 N 層樓的建築。

每個蛋的功能都是一樣的,如果一個蛋碎了,你就不能再把它掉下去。

你知道存在樓層 F ,滿足 0 <= F <= N 任何從高於 F 的樓層落下的雞蛋都會碎,從 F 樓層或比它低的樓層落下的雞蛋都不會破。

每次移動,你可以取一個雞蛋(如果你有完整的雞蛋)並把它從任一樓層 X 扔下(滿足 1 <= X <= N)。

你的目標是確切地知道 F 的值是多少。

無論 F 的初始值如何,你確定 F 的值的最小移動次數是多少?

示例 1:

輸入:K = 1, N = 2
輸出:2
解釋:
雞蛋從 1 樓掉落。如果它碎了,我們肯定知道 F = 0 。
否則,雞蛋從 2 樓掉落。如果它碎了,我們肯定知道 F = 1 。
如果它沒碎,那麼我們肯定知道 F = 2 。
因此,在最壞的情況下我們需要移動 2 次以確定 F 是多少。

示例 2:

輸入:K = 2, N = 6
輸出:3
解題思路

這個題需要再O(KN)O(K*N)或者O(KNlogN)O(K*N*logN)的時間複雜度下解決
對於雞蛋掉落問題,不難寫出它的狀態轉移方程:
dp(N,K)=1+min1XN(max(dp(X1,K1),dp(NX,K)) dp(N,K)=1+min_{1\leq X\leq N}(max(dp(X-1,K-1),dp(N-X,K))
這樣我們便可枚舉樓層、雞蛋和摔落樓層寫出一個O(KN2)O(K*N^2)的算法
不過這個解法無法在限定的時間內通過這題。

dp(X1,K1)dp(X-1,K-1)是一條斜率爲正的函數折線
dp(NX,K)dp(N-X,K)是一條斜率爲負的函數折線
這兩個函數的交點X0X_{0}便是使得狀態方程的最優解

實際上dp(X1,K1)dp(X-1,K-1)是不受N增加影響的,因爲它只考慮了KK層,與後面的NKN-K層無關,所以當NN增加時,最優解X0X_{0}也會增加,這樣便構成了這裏動態規劃的決策單調性。

Code
class Solution {
public:
    int superEggDrop(int K, int N) {
        int dp[N+1];
        for(int i=0;i<=N;++i) dp[i]=i;
        for(int i=2;i<=K;++i){
            int t[N+1];
            t[0]=0;
            int x=1;
            for(int n=1;n<=N;++n){
            	//決策單調性
                while(x<n&&max(dp[x-1],t[n-x])>=max(dp[x],t[n-x-1])) ++x;
                t[n]=max(dp[x-1],t[n-x])+1;
            }
            for(int n=1;n<=N;++n) dp[n]=t[n];
        }
        return dp[N];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章