首页 > 其他分享 >【动态规划】高楼扔鸡蛋问题

【动态规划】高楼扔鸡蛋问题

时间:2023-01-17 22:00:10浏览次数:61  
标签:return floor 鸡蛋 次数 高楼 memory 动态 eggs

目录

高楼扔鸡蛋

这是一个比较经典的动态规划问题,最先来自谷歌的面试题。

题目

887. 鸡蛋掉落

方法一:动态规划

分析

我们假设 \(g(k, n)\) 表示当有 \(k\) 枚鸡蛋,楼层数为 \(n\) 时,找到临界楼层 \(F\) 所需要的最小操作次数。

边界条件

当楼层数为零时,查找次数为 \(0\) ,当鸡蛋数量为 \(1\) 时,我们需要一层一层地查找,因此,最坏的情况下,查找次数等于楼层数 \(n\),因此:

\[\begin{gather*} g(0, i) = 0, \quad 1 \le i \le n\\ g(1, i) = n, \quad 1 \le i \le n \end{gather*} \]

状态转移

我们考虑一般情况,对于第 \(i\) 层楼:

\[\underbrace{1,\ 2,\ \cdots, \ i-1}, \ i, \underbrace{\ i+1,\ \cdots,\ n-1, \ n} \]

当我们从第 \(i\) 层楼扔下一枚鸡蛋的时候,这枚鸡蛋有两种状态,鸡蛋碎了或者不碎,那么:

  • 若鸡蛋没有碎

    我们可以继续用 \(k\) 枚鸡蛋,在上方的楼层,即 \(i + 1, \cdots, n\),共 \(n - i\) 层楼中,继续寻找 \(F\),因此,所需要查找的次数为 \(g_1=g(k, n - i)\) ;

  • 若鸡蛋碎了

    这时,鸡蛋的数量少了一枚,因此,我们就需要用剩余的 \(k - 1\) 枚鸡蛋,在下方的楼层,即 \(1, \cdots, i - 1\),共 \(i - 1\) 层楼中,继续寻找 \(F\),因此所需要查找的次数为 \(g_2=g(k - 1, i - 1)\) 。

这里,我们可以看到,通过状态转移,明显将问题的规模缩小了,由于题目是要求在最坏的情况下,扔鸡蛋的最少次数,所以,最坏的情况下,在第 \(i\) 层楼的操作次数,取决于 \(g_1\) 和 \(g_2\) 的最大值。

因此,在最坏的情况下,最少的操作次数为:

\[g(k,n) = \min^n_{i=1}(\max(g_1, \ g_2)) = \min^n_{i=1}(\max(g(k, n - i), \ g(k - 1, i - 1))) \]

代码实现

class Solution:
    def superEggDrop(self, k: int, n: int) -> int:
        """
        :param k: the number of eggs
        :param n: the number of floor
        :return: 最坏情况下最少的尝试次数
        """
        memory = dict()
        min_count = self.drop_egg(k, n, memory)
        return min_count

    def drop_egg(self, eggs: int, floor: int, memory: Dict) -> int:
        # 边界条件:如果楼层数量为0,查找次数为0
        if floor == 0:
            return 0
        # 如果只剩一个鸡蛋,就必须一层一层地查找
        if eggs == 1:
            return floor
        if (eggs, floor) in memory:
            return memory.get((eggs, floor))

        result = float("INF")
        for i in range(1, floor + 1):
            result = min(result, max(self.drop_egg(eggs, floor - i, memory), self.drop_egg(eggs - 1, i - 1, memory)) + 1)

        memory[(eggs, floor)] = result
        return result

复杂度

复杂度分析:

  • 时间复杂度:\(O(kn^2)\);
  • 空间复杂度:\(O(kn)\)。

注:这种方法,直接枚举所有的状态,在力扣上提交的时候,会超时,因此,我们还需要对上述算法做进一步优化。

方法二

分析

结合前面的分析,我们可以看出:

  • \(g_1=g(k, \ n - i), \ 1 \in [i, n]\) 是一个随 \(i\) 增加的单调递减函数;
  • \(g_2=g(k - 1, \ i - 1),\ 1 \in [i, n]\) 是一个随 \(i\) 增加的单调递增函数;

因此,

标签:return,floor,鸡蛋,次数,高楼,memory,动态,eggs
From: https://www.cnblogs.com/larry1024/p/17057913.html

相关文章

  • jQuery(自定义动画/导航动态显示效果)
    视频自定义动画<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>24_自定义动画</title><styletype="text/css">*{margin:0px;......
  • BLE动态广播与连接
    一、动态广播内容动态修改广播包需要对广播包里面的数据进行重新赋值即可。通过TMOS任务处理。if(events&DYNAMIC_advertData)//动态广播包内容{......
  • Linux环境中动态库文件(.so文件)的realname,soname和linkname
     realname:实际等同于库文件的filename,是在库文件生成时就被指定的,如:gcc-shared-o$(realname)dependenceflagsrealname的一般格式为lib$(name).so.$(major).$(......
  • Linux动态库soname的使用
    通过一个简单的例子,体验一下Linux动态库soname的使用。假设有一个动态库:libbar.so.1.1.0,其对应的三个名称如下。realname:libbar.so.1.1.0soname:libbar.so.1linkname:l......
  • Linux动态链接库.so文件的命名及用途总结
    我们在linux下开发项目,有时会对外提供动态库,像***.so.1.0.0这样子的文件,另外提供相应的头文件。用户拿到动态库和头文件说明,就可以使用动态库里的function。那随之而来......
  • React: 动态添加样式
    问题背景在软件开发过程中,经常会出现动态添加style或className,比如:同一个表格组件在A处调用,需要固定前四列数据,B处调用则不用,那这时候,动态添加元素就派上了用场。解决方......
  • JPA动态注册多数据源
    背景目前已经是微服务的天下,但是随着业务需求的日益增长,部分应用还是出现了需要同时连接多个数据源操作数据的技术诉求。需要对现有的技术架构进行优化升级,查阅了下网上......
  • CAD动态块操作实例:绘制剖面符号
    CAD动态块与普通的CAD图块相比,其图形夹点更多,设计师可以利用动态块的夹点对图形进行快速调整,自由拉伸长度、随心切换隐藏形态等。本节,给大家分享一下浩辰CAD软件中利用CAD......
  • ABAP Memory Inspector 里对动态内存对象的内存消耗度量方式
    ABAP静态内存对象是其大小在设计时由数据类型声明设置的对象。除非更改程序代码本身,否则程序中此类变量占用的内存不会更改。在ABAP术语中,静态变量也称为flatvariab......
  • 【Javaweb】动态web工程目录介绍
    src存放自己编写的Java源代码web专门用来存放web工程的资源文件(html页面、css文件、js文件等等)WEB-INF是一个受服务器保护的目录,浏览器无法直接访问此目录的内容web.......