高楼扔鸡蛋问题

问题描述:一共有n层楼,和m个鸡蛋,要保证最大多少层楼可以保证鸡蛋不碎,需要最少的测试次数。
1、若鸡蛋个数足够多,使用二分法肯定是最优解
最坏情况下的最少测试次数:ceil(logn)
2、若鸡蛋个数不够,这个时候就不能使用二分法了
我们使用动态规划来解决一下这类问题。
1、拆分子问题
若从k层扔下,可以用于测试的鸡蛋有m个
这时有两种情况:a、鸡蛋碎了,这时应该去k层下面进行测试,鸡蛋个数减一。b、鸡蛋没碎,这时可以去第k层上面进行测试,鸡蛋个数不变
dp[k][m]=min{dp[k][m],max{dp[k-1][m-1],dp[n-k][m]}+1}
那么第层的最少测试次数可以总结为dp[k][m]表示当前层是测试的最后一层,或者从第k层的上面或下面找到最坏情况的测试次数,加一表示当前层测试了一次。
`

include <bits/stdc++.h>

using namespace std;

int dp[1005][105]; // 假设最大n和m分别为1000和100

int test(int n, int m) {
if (m == 1)
return n;
if (n == 0)
return 0;

if (dp[n][m] != -1)
    return dp[n][m];

int ret = numeric_limits<int>::max();
int low = 1, high = n;

while (low <= high) {
    int mid = (low + high) / 2;
    int break_case = test(mid - 1, m - 1);
    int no_break_case = test(n - mid, m);
    
    // We take the worst case scenario
    int temp = max(break_case, no_break_case) + 1;
    
    if (break_case > no_break_case) {
        high = mid - 1;
    } else {
        low = mid + 1;
    }
    
    ret = min(ret, temp);
}

return dp[n][m] = ret;

}

int main() {
int n, m;
cin >> n >> m;

memset(dp, -1, sizeof(dp));
cout << test(n, m);
return 0;

}
`
时间复杂度:O(nmlogn)

posted @ 2024-09-14 14:33  jenniferCAI  阅读(121)  评论(0)    收藏  举报