力扣887题(高楼扔鸡蛋)

887、高楼扔鸡蛋

第一种解法:二分搜索+动态规划

具体实现:

1.定义函数dp(k,n)

当前状态下为k个鸡蛋,面对n层楼,返回这个状态下最少的扔鸡蛋次数

2.选择在第i层楼扔,出现两种情况

 (1)鸡蛋碎了 ,鸡蛋个数-1,往下面的楼找,dp(k-1,i-1),随着i增大,函数增大,单调递增

 (2)鸡蛋没碎,鸡蛋个数不变,往上面的楼找,dp(k,N-i),随着i增大,函数减小,单调递减

3.求两个函数的较大值,在求这些较大值之中的最小值,其实就是求两条直线的交点,也是折线的最低点

4.状态转移方程:

dp(k,n) = min(max(dp(k-1,i-1),dp(k,n-i))+1)

代码:

class Solution:
    def superEggDrop(self, k: int, n: int) -> int:
        memo = dict()
        def dp(k,n):
            if k == 1:return n
            if n == 0:return 0
            if (k,n) in memo:
                return memo[(k,n)]
            
            res = float('INF')
            lo,hi = 1,n
            while lo <= hi:
                mid = (lo+hi)//2
                broken = dp(k-1,mid-1)
                not_broken = dp(k,n-mid)
                if broken > not_broken:
                    hi = mid-1
                    res = min(res,broken+1)
                else:
                    lo = mid+1
                    res = min(res,not_broken+1)

            memo[(k,n)] = res
            return res
        return dp(k,n)

第二种解法:重新定义状态转移

具体实现:

1.dp[k][m] = n

当前有k个鸡蛋,最多可以尝试扔m次

在这个状态下,最坏情况下最多能确切测试一栋n层的楼

2.状态转移方程

dp[k][m] = dp[k][m-1] +dp[k-1][m-1]+1

总的楼层数 = 楼上的楼层数+楼下的楼层数+当前这一层

代码:

class Solution:
    def superEggDrop(self, k: int, n: int) -> int:
        dp = [[0]*(n+1) for _ in range(k+1)]
        m = 0
        while dp[k][m] < n:
            m = m + 1
            for i in range(1,k+1):
                dp[i][m] = dp[i][m-1] + dp[i-1][m-1] +1
        return m
原文地址:https://www.cnblogs.com/zhaojiayu/p/14557534.html