887. 雞蛋掉落
給你 k 枚相同的雞蛋,并可以使用一棟從第 1 層到第 n 層共有 n 層樓的建筑。
已知存在樓層 f ,滿足 0 <= f <= n ,任何從 高于 f 的樓層落下的雞蛋都會碎,從 f 樓層或比它低的樓層落下的雞蛋都不會破。
每次操作,你可以取一枚沒有碎的雞蛋并把它從任一樓層 x 扔下(滿足 1 <= x <= n)。如果雞蛋碎了,你就不能再次使用它。如果某枚雞蛋扔下后沒有摔碎,則可以在之后的操作中 重復使用 這枚雞蛋。
請你計算并返回要確定 f 確切的值 的 最小操作次數 是多少?
示例 1:輸入:k = 1, n = 2
輸出:2
解釋:
雞蛋從 1 樓掉落。如果它碎了,肯定能得出 f = 0 。
否則,雞蛋從 2 樓掉落。如果它碎了,肯定能得出 f = 1 。
如果它沒碎,那么肯定能得出 f = 2 。
因此,在最壞的情況下我們需要移動 2 次以確定 f 是多少。
示例 2:輸入:k = 2, n = 6
輸出:3
示例 3:輸入:k = 3, n = 14
輸出:4
解題思路
使用dp+二分
- n*100+k 編號每一種n和k的情況。
- 狀態轉移方程為:當x為不同樓層時,dp[k][n]=1+max(dp[k-1][x-1],dp[k][n-x]),在雞蛋在樓層x摔壞以后排查下面x-1層和雞蛋沒有摔壞向上排查n-x層取最壞情況的操作次數
- 我們發現當x遞增的時候,操作次數也會不斷減少,因此 dp[k-1][x-1],dp[k][n-x]是具有相反的單調性的,而我們又必須取二者最壞情況,所以我們可以二分查找x,盡量找出dp[k-1][x-1],dp[k][n-x]最接近的x,就是可取地的最小操作次數
代碼
class Solution {Map<Integer,Integer> map=new HashMap<>();public int superEggDrop(int k, int n) {int cur=n*100+k;if(n==0)return 0;if(k==1)return n;if(map.containsKey(cur))return map.get(cur);int l=1,r=n,res=Integer.MAX_VALUE;while(l<=r){int mid=(r-l)/2+l;int lv=superEggDrop(k-1,mid-1),rv=superEggDrop(k,n-mid);if(lv>rv){r=mid-1;res=Math.min(1+lv,res);}else {l=mid+1;res=Math.min(1+rv,res);}}map.put(cur,res);return map.get(cur);}
}