public class Solution {
public int solve (int n, int k) {
if(k == 1) {
return n;
}
if(n == 0) {
return 0;
}
// 相当于对最高楼层 n 进行二分查找,h相当于log2(n) + 1
int h = (int)(Math.log(n) / Math.log(2))+1;
// 如果k很大, 二分的扔即可,只是一种特殊情况
if(k > h) {
return h;
}
// dp数组定义:确定当前的棋子个数k,能够确定的最高楼层数h
int[] dp = new int[k];
// base case:没有棋子,最多测0层
dp[0] = 0;
// base case:只有一个棋子,最坏情况下最多只能测一层楼
dp[1] = 1;
// 统计扔的次数
int res = 1;
while(true){
// dp_i_1相当于dp[i-1]
int dp_i_1 = 0;
// 状态压缩后:
// dp[i] = dp[i] + dp[i-1] + 1
// 因为dp[i][j] 依赖的是左边和左上, 为了防止覆盖, 需要倒着计算
for(int i = 0; i < k; i++){
int temp = dp[i];
// 相当于dp[i] = dp[i] + dp[i-1] + 1, dp_i_1相当于dp[i-1]
dp[i] += dp_i_1 + 1;
// 保存作为下一次的dp[i-1]
dp_i_1 = temp;
// 能够确定到最高层 n, 返回结果
if(dp[i] >= n) {
return res;
}
}
// 每一轮迭代 次数增加1,相当于确定最高楼层n允许扔的次数
res++;
}
}
}