2个鸡蛋,六层楼,可以通过递归的方法来解决,由于有重复子问题,将这些子问题记录下来。
利用记忆话递归来解决(Python):
class Solution:
def superEggDrop(self, K: int, N: int) -> int:
@lru_cache(None)
def dp(k, n):
if k == 0: return 0
if k == 1: return n
if n <= 1: return n
res = n
for i in range(1, n + 1):
res = min(res, max(dp(k - 1, i - 1) + 1, dp(k, n - i) + 1))
return res
return dp(K, N)
标准的迭代动态规划(超时):
class Solution {
public:
int superEggDrop(int k, int n) {
vector<vector<int>> f(n + 1, vector<int>(k+1, INT_MAX));
for(int i = 0; i <= k; i++) {
f[0][i] = 0;
}
for(int i = 0; i <= n; i++) {
f[i][1] = i;
f[i][0] = 0;
}
for(int p = 2; p <= k; p++) {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
f[i][p] = min(f[i][p], max(f[j - 1][p - 1] + 1, f[i - j][p] + 1));
}
}
}
return f[n][k];
}
};
这里再求解子问题的时候,这里注意到dp[k-1,i - 1] 关于i单增和dp[k, n - i]关于i单调减小,因此
、
最大值得最小值可以通过二分来求解:
class Solution:
def superEggDrop(self, K: int, N: int) -> int:
@lru_cache(None)
def dp(k, n):
if k == 0: return 0
if k == 1: return n
if n <= 1: return n
left, right = 1, n
while left <= right:
mid = (left + right) // 2
if dp(k-1, mid - 1) >= dp(k, n - mid):
right = mid - 1
else:
left = mid + 1
res = 1 + max(dp(k - 1, left - 1), dp(k, n - left))
return res
return dp(K, N)