继续讲故事~~

  这天,丁丁正走在路上,欣赏着路边迷人的城市风景,突然发现前面的大楼前围了一波吃瓜群众。他好奇地凑上前去,想一探究竟,看看到底发生了什么事情。

  原来本市的一位小有名气的科学家正在这幢大楼进行一个实验:某种材料的防护性能。他在大楼的底下铺了一层这种防护材料,想拿鸡蛋做实验,将鸡蛋从楼层掉下,看看鸡蛋从哪一层掉下去会摔碎,以此测试该材料的防护性能。这就是著名的鸡蛋掉落问题(egg dropping problem),即给定N个鸡蛋和k层楼,试问至少需要几次才能确定鸡蛋从哪一层楼掉下去恰好摔碎。

  一听到这个问题,他顿时感觉无从下手,没有丝毫的头绪。但他尝试着先从最简单的情形入手:

  • 若鸡蛋数N=0或者楼层数为0,则尝试0次即可。
  • 若鸡蛋数N=1, 对于楼层数为k,最坏的情况为尝试k次,因此至少需要k次才能确定鸡蛋从哪一层楼掉下去恰好摔碎。

有了最基本的情形还不够,对于其他的N,k并没有给出答案。这时,他想到自己这几天正在研究的算法:动态规划法,他想也许这个算法可以帮上忙。假设用numdrops(N,k)表示该问题的解。则将鸡蛋从x层扔下,有以下两种情形:

  • 鸡蛋摔碎了,此时剩下N-1个鸡蛋,需要考虑比x层低的楼层,即1,2,...,x-1层,因为比x层高的楼层扔下去必定也摔碎,故可不比考虑。因此,这个问题会被缩减到numdrops(N-1, x-1).
  • 鸡蛋没有摔碎,此时剩下N个鸡蛋,需要考虑比x层高的楼层,即x+1, x+2,...,k层,共有k-x层。因此,问题会被缩减到numdrops(N, k-x).

对于以上两种情形,应该去两者的最大值。同时,考虑到x=1,2,3,...,k, 因此有如下公式:

\[numdrops(N,k)=1+\min\limits_{1\leq x\leq k}\{\ max(numdrops(N-1, x-1), numdrops(N, k-x))\}.
\]

有了以上算法,再加上如下初始情况:

  • numdrops(0, x)=0, numdrops(x,0)=0.
  • numdrops(1, x)=x.

就可以用动态规划法求解该问题了。他迅速地写下了Python代码:

import numpy as np

def solvepuzzle(n, k):
numdrops = np.array([[0]*(k+1)]*(n+1)) for i in range(k+1):
numdrops[1, i] = i for i in range(2, n+1):
for j in range(1, k+1):
minimum = float('inf') for x in range(1, j+1):
minimum = min(minimum, (1+max(numdrops[i, j-x], numdrops[i-1, x-1]))) numdrops[i, j] = minimum print(numdrops)
return numdrops[n,k] t = solvepuzzle(3, 10)
print(t)

输出结果如下:

[[ 0  0  0  0  0  0  0  0  0  0  0]
[ 0 1 2 3 4 5 6 7 8 9 10]
[ 0 1 2 2 3 3 3 4 4 4 4]
[ 0 1 2 2 3 3 3 3 4 4 4]]
4

这样就可以求出该问题的解了,比如4个鸡蛋10层楼,则只需要3次即可。

  丁丁连忙把这个解答问题通过助手告诉了科学家。科学家听后兴奋不已,立马叫丁丁过来讨论。科学家对他说道:“你的解决方法是如此的巧妙,让人叹为观止,很难相信它是出自一个少年的脑袋中。但是,亲爱的朋友,你能告诉我具体应该怎么扔鸡蛋呢?”

  丁丁听了,又是欢喜又有点担心,因为科学家又提出了一个问题。他看看了输出的numdrops表格,立马就有了主意。

  对于N=2,k=50的情形,numdrops(N,k)=10,给出的方案如下:

从哪一层扔鸡蛋 鸡蛋摔碎后的情形 次数
10 1->2->3->4->5->6->7->8->9 9+1=10
19 11->12->13->14->15->16->17->18 8+2=10
27 20->21->22->23->24->25->26 7+3=10
34 28->29->30->31->32->33 6+4=10
40 35->36->37->38->39 5+5=10
45 41->42->43->44 4+6=10
49 46->47->48 3+7=10
50 8

尝试着对上表做说明:先从第10层扔下,若鸡蛋摔了,则还剩一个鸡蛋,依次从1,2,3...9层扔下,若鸡蛋没碎,则失去了一次尝试机会,再将鸡蛋从19层扔下,若鸡蛋碎了,则还剩一个鸡蛋,依次从11,12,...,18层扔下......

  对于N=4,k=20的情形,numdrops(N,k)=10,输出的numdrops表如下:

[[ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
[ 0 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6]
[ 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 5 5 5 5 5 5]
[ 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5 5]]
5

首先找到numdrops(3,14)=4, 次数比5小一次, 层楼k尽可能大,则将鸡蛋从15扔下,若鸡蛋没碎,则剩下3个鸡蛋,探索4层楼,因为numdrops(3,14)=4,故能完成。若鸡蛋碎了,则再找到numdrops(2,6)=3,则将鸡蛋从7楼扔下,若鸡蛋碎了,则情形转化为numdrops(2,6)的情形,若鸡蛋没碎,则用剩下的鸡蛋探索7层楼,是可以搞定的。

  当科学家看到这个结果后,满意地点点头,他想着是否要聘请这个少年来当自己的助手。不过,他决定再考验丁丁一回~~

  未完待续~~

注意:本人现已开通两个微信公众号: 用Python做数学(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~

动态规划法(六)鸡蛋掉落问题(一)(egg dropping problem)的更多相关文章

  1. 记录Leetcode 鸡蛋掉落 的思路

    前言 首先看一下这个题目,是Leetcode的第887题"鸡蛋掉落": 你将获得 `K` 个鸡蛋,并可以使用一栋从 `1` 到 `N` 共有 `N` 层楼的建筑. 每个蛋的功能都是 ...

  2. Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)

    887. 鸡蛋掉落 你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑. 每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去. 你知道存在楼层 F ,满足 0 < ...

  3. 1. 线性DP 887. 鸡蛋掉落 (DP+二分)

    887. 鸡蛋掉落 (DP+二分) https://leetcode-cn.com/problems/super-egg-drop/ /*首先分析1个蛋,1个蛋的话,最坏情况需要N次,每次只能从0 1 ...

  4. [Swift]LeetCode887. 鸡蛋掉落 | Super Egg Drop

    You are given K eggs, and you have access to a building with N floors from 1 to N. Each egg is ident ...

  5. [LeetCode] 887. Super Egg Drop 超级鸡蛋掉落

    You are given K eggs, and you have access to a building with N floors from 1 to N.  Each egg is iden ...

  6. 扔鸡蛋问题具体解释(Egg Dropping Puzzle)

    经典的动态规划问题,题设是这种: 假设你有2颗鸡蛋,和一栋36层高的楼,如今你想知道在哪一层楼之下,鸡蛋不会被摔碎,应该怎样用最少的測试次数对于不论什么答案楼层都可以使问题得到解决. 假设你从某一层楼 ...

  7. 扔鸡蛋问题详解(Egg Dropping Puzzle)

    http://blog.csdn.net/joylnwang/article/details/6769160 经典的动态规划问题,题设是这样的:如果你有2颗鸡蛋,和一栋36层高的楼,现在你想知道在哪一 ...

  8. Egg Dropping Puzzle问题的分析

    首先,基本问题是这样:You are given two eggs, and access to a 100-storey building. The aim is to find out the h ...

  9. LeetCode 887.鸡蛋掉落(C++)

    每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去. 你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的 ...

随机推荐

  1. Maven学习 一 概念介绍

    一 Maven是什么 Maven是一个Apache公司的开源项目,主要有两个作用:(1)是项目构建工具.(2)是用来管理java程序中jar包的依赖. 它包含了一个项目对象模型(Project Obj ...

  2. php memcache 基础操作

    <?php/** * Memcache缓存操作 * @author hxm * @version 1.0 * @since 2015.05.04 */class MCache extends O ...

  3. 解决刚刚安装完mysql 远程连接不上问题

    解决远程连接mysql错误1130 远程连接Mysql服务器的数据库,错误代码是1130,ERROR 1130: Host xxx.xxx.xxx.xxx  is not allowed to con ...

  4. MySQL缓存参数优化(转)

    MySQL 数据库性能优化之缓存参数优化 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在 ...

  5. form表单保存和取出

    function saveConfig() { var configName = document.title; if (!localStorage) return; var Config = {}; ...

  6. 使用Linux自带日志滚动工具logrotate滚动redis日志示例

    截至到redis-5.0版本,redis仍然不会自动滚动日志文件,如果不处理则日志文件日积月累越来越大,最终将导致磁盘满告警: # ls -lh total 12G -rw-r--r-- 1 redi ...

  7. _ZNote_Qt_Tips_添加动态链接库

    之前添加都是 手写添加,今天陈老师提示可以在 .pro 文件内空白处,右键弹出添加

  8. 使用Jupyter Notebook编写技术文档

    1.jupyter Notebook的组成 这里它的组件及其工程构成,帮助大家更好的用好jupyter Notebook 组件 Jupyter Notebook结合了三个组件: 笔记本Web应用程序: ...

  9. Ubuntu 安装 chrome浏览器

    按下 Ctrl + Alt + t 键盘组合键,启动终端. 输入以下命令: sudo wget http://www.linuxidc.com/files/repo/google-chrome.lis ...

  10. RabbitMQ 常用操作

    RabbitMQ简介 1.首先安装erlang rpm -Uvh https://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos ...