博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
鹰蛋问题解析之动态规划
阅读量:4074 次
发布时间:2019-05-25

本文共 1733 字,大约阅读时间需要 5 分钟。

一幢 100 层的大楼,给你两个鸡蛋。如果在第 n 层扔下鸡蛋,鸡蛋不碎,那么从第 n-1 层扔鸡蛋,都不碎。这两只鸡蛋一模一样,不碎的话可以扔无数次。最高从哪层楼扔下时鸡蛋不会碎?

1. 如果有无数个蛋

如果问题分为两问,第一问提出如果你鹰蛋有无数个,该如何求解?这个问题比较简单,只需要二分法就能在O(lgn)的次数内求解问题,问题的第二问是如果只有两个鹰蛋,该如何求解,我当时的给的答案如下:

2.一种方案,把楼层等分试探求解

把楼层分为x等分,用第一鹰蛋从下往上依次试探一个范围,如果第一个鹰蛋破了,则用另一鹰蛋穷举。

假如将100层楼分为20等分,则用第一个鹰蛋分别在第5层,第10层,第15层。。。。依次试探,假如在35层鹰蛋破碎,则用另一个鹰蛋从31层到34层依次试探,则可以求出破蛋的临界点。

上面的方法的最坏情况是鹰蛋的临界点在N-1层(N代表总楼层数),也就是倒数第二层。因为这时候第一个蛋把所有的等分楼层都尝试了一遍,而且第二个蛋也要把一个等分内部的楼层全部尝试一遍。

假设把总楼层分成了X等份,每个等分内部有N/X个楼层。

在最坏情况下,第一个蛋需要试探X次,第二蛋则要试探N/X - 1次(即在每个等份内做穷举),所以最坏情况需要的总次数为X + (N/X) -1。

要获取最坏情况的最小值,需要对总次数X + (N/X) -1求导数,并取0值,即:

(X + (N/X) -1)'(求导)

=1- (N/X2

=0

求解,可以得到X = sqrt(N)。

在楼层=100的情况下,可以求出使总次数最小的X=10,也就是说如果采用等份的办法,在楼层总数是100时,10等份是最优情况。

3.最终答案:动态规划

鹰蛋问题的最优解,可以通过动态规划的办法来实现,假设有m楼层,n个鹰蛋,则在第i层试探时会出现两种状态,一种状态是鹰蛋摔破了,则我们下一步只有n-1个鹰蛋,同时总楼层数也缩减为i-1,另一种状态是鹰蛋没有摔破,那么鹰蛋总数不变,还是n个,楼层数则缩减为m-i层。

这样一个问题就被分解为两个规模更小的子问题,通过递归的方式求解,递归在以下3个状态结束:1)如果鹰蛋只剩1个,那么只能对所有的楼层进行穷举;2)如果楼层是0,则需要试探0次; 3)如果楼层是1,则需要只需要试探1次。

动态规划的状态转移方程如下:

F(m,n)= MIN{ MAX{ F(i-1, n-1) + 1, F(m-i, n)+1}};(0 < i < m)

通过方程可以看出,再递归的过程中会重复的解子问题,通过array[M][N]来保存子问题的结果,提高效率,代码如下:

const int nfloor = 100;const int negg = 2;#define MAX(a, b) (a) > (b) ? (a) : (b)int arr[nfloor][negg];int test_egg(int nfloors, int neggs){		if(neggs <= 1)		return nfloors;	if(nfloors == 0)		return 0;	if(nfloors == 1)		return 1;	int min = nfloor;	if(arr[nfloors-1][neggs-1] != 0)		return arr[nfloors-1][neggs-1];	for(int i = 1; i < nfloors; i++)	{		int a = test_egg(i-1, neggs-1) + 1;			int b = test_egg(nfloors - i, neggs) + 1;		int v = MAX(a, b);		if(min >  v)			min = v;	}	arr[nfloors-1][neggs-1] = min;	return min;}int main(int argc, _TCHAR* argv[]){	memset(arr, 0, nfloor*negg*sizeof(int));	int a = test_egg(nfloor,negg);	return 0;}

你可能感兴趣的文章
大数据入门:Hive和Hbase区别对比
查看>>
大数据入门:ZooKeeper工作原理
查看>>
大数据入门:Zookeeper结构体系
查看>>
大数据入门:Spark RDD基础概念
查看>>
大数据入门:SparkCore开发调优原则
查看>>
大数据入门:Java和Scala编程对比
查看>>
大数据入门:Scala函数式编程
查看>>
【数据结构周周练】002顺序表与链表
查看>>
C++报错:C4700:使用了非初始化的局部变量
查看>>
【数据结构周周练】003顺序栈与链栈
查看>>
C++类、结构体、函数、变量等命名规则详解
查看>>
C++ goto语句详解
查看>>
【数据结构周周练】008 二叉树的链式创建及测试
查看>>
《软件体系结构》 第九章 软件体系结构评估
查看>>
《软件体系结构》 第十章 软件产品线体系结构
查看>>
《软件过程管理》 第六章 软件过程的项目管理
查看>>
《软件过程管理》 第九章 软件过程的评估和改进
查看>>
分治法 动态规划法 贪心法 回溯法 小结
查看>>
《软件体系结构》 练习题
查看>>
《数据库系统概论》 第一章 绪论
查看>>