LeetCode 887. 鸡蛋掉落(DP+二分)

题目链接:https://leetcode-cn.com/problems/super-egg-drop/

 

题目大意:

  有K个鸡蛋,N层楼。第F层楼及以下鸡蛋扔下去不会碎,以上扔下去会碎,如果扔下去没碎还能继续用,否则就没了。问最少多少次能够保证无论F是哪一层都能测出来。
 

题目思路:

  看了半天没看出是DP…首先可以发现一个事情,如果只有一个鸡蛋,那么想试只能从一楼慢慢往上了,否则鸡蛋碎了就凉了。如果有无数个鸡蛋,但是只有一楼,那么也当且仅当一次是需要的。这就是dp的预处理。
  接下来咋办呢?可以这么考虑DP方程。如果现在有K个鸡蛋,N层楼,那么这个鸡蛋可能是从X层楼开始实验,那么接下来有两种情况:

  • 鸡蛋碎了。那么鸡蛋变K-1个,但是可以发现F肯定小于X,所以接下来需要测试的楼层数就变成了X-1,那么接下来需要的次数就是dp[K-1][X-1]
  • 鸡蛋没碎。那么鸡蛋还是K个,但是说明答案是当前或者以上楼层,只需要测试上面的楼层,需要测的数量变N-X,那么需要的次数就是dp[K][N-X]

  然后就可以根据找个进行DP转移了,要么碎了要么没碎,因为要百分百能测出来,所以要取这俩中的最大值,不然大的那种情况发生了咋办,不就测不出来了么。但是可以发现,这个X还需要遍历,复杂度太高了,但是我们还能发现, m a x ( d p [ K − 1 ] [ X − 1 ] , d p [ K ] [ N − X ] ) max(dp[K-1][X-1],dp[K][N-X]) max(dp[K1][X1],dp[K][NX])有一个牛逼的性质,那就是随着x的增大dp[K-1][X-1]非递减,dp[K][N-X]非递增,那么那个交点的位置就是要找的最小值,直接二分找到dp[K][N-X]大于dp[K-1][X-1]的最靠右的位置,因为我们要的是整数点,但是可能是小数,所以小数两头的整数都得试试,也就是试试这个二分出来的点x和这个点+1,取最小值。

  太久没写代码,能力退化的非常严重。。(本来就菜),最近状态也有点不好需要加油了!

 

以下是代码:

class Solution {
public:
int dp[105][10005];
int superEggDrop(int K, int N) {
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=N;i++)dp[1][i]=i;
    for(int i=1;i<=K;i++)dp[i][1]=1;
    for(int i=2;i<=K;i++){
        for(int j=2;j<=N;j++){
            int l=1,r=j,ans=1;
            while(l<=r){
                int mid=(l+r)>>1;
                if(dp[i][j-mid]>dp[i-1][mid-1]){
                    ans=mid;
                    l=mid+1;
                }
                else r=mid-1;
            }
            dp[i][j]=1+min(max(dp[i][j-ans],dp[i-1][ans-1]),max(dp[i][j-ans-1],dp[i-1][ans]));
        }
    }
    return dp[K][N];
}
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值