具体思路:
二分+DP;
有点扯的一题,DP好理解,难理解的是二分,为什么就单调了?
具体代码:
class Solution {
public:
int superEggDrop(int K, int N) {
if (K == 1) return N;
if (N == 1) return 1;
vector<vector<int>> dp(N + 1, vector<int>(K + 1, 0));
// 初始化dp数组
for (int i = 1; i <= N; i++) dp[i][1] = i;
for (int k = 1; k <= K; k++) dp[1][k] = 1;
for (int i = 2; i <= N; i++) {
for (int k = 2; k <= K; k++) {
/*
int res = INT_MAX;
for (int j = 1; j <= i; j++) {
res = min(res, max(dp[j - 1][k - 1], dp[i - j][k]) + 1);
}
*/
// 这一段改用二分查找,而不从1枚举到i
int start = 1, end = i, mid;
int res = INT_MAX;
// 可能存在找不到的情况,因为两者的交点一定存在,但是横坐标不一定是一个整数,因此这里的res记录必不可少
// 在没有整数交点的情况下,res会记录到交点两侧的的横坐标对应的较小值
// 存在整数交点的情况下,res自然就记录到了整数交点处的最小值
while (start <= end) {
mid = start + (end - start) / 2;
if (dp[mid-1][k-1] == dp [i-mid][k]) {
res = min(res, dp[mid-1][k-1] + 1);
break;
} else if (dp[mid-1][k-1] > dp[i-mid][k]) {
end = mid - 1;
res = min(res, dp[mid-1][k-1] + 1);
} else {
start = mid + 1;
res = min(res, dp[i-mid][k] + 1);
}
}
dp[i][k] = res;
}
}
return dp[N][K];
}
};