最高安全横档问题(100层台阶瓶子不摔碎的最高高度)

原题


某个厂家需要对一批玻璃罐进行压力测试来检测它们在多大的高度摔下而不致破裂。具体的实验为: 一副具有n个横档的梯子,测试罐子可从其摔下而不破的最高的那节横档,此值称为罐子的最高安全横档。一个简单的办法也许可以采用二分法,但这有可能弄破很多罐子,请找个时间代价低于线性时间的办法,在只摔破两个罐子的前提上求出罐子的最高安全横档。


问题简化


有一种瓶子,最高耐摔高度不超过 n 阶,如果只有两个瓶子,如何用最快的时间测出瓶子的最高耐摔高度?如果有k个瓶子呢?


问题解答


1. 2 个瓶子的情形

不失一般性,设n是个完全平方数,我们把第 1 个瓶子从高度为nt阶的地方下落直至破碎。

假设瓶子在 nj 时破碎,那么最高安全横档高度在 nj1 nj 之间。接下来,我们把 2 个瓶子从1+nj1开始尝试, 1 次试1阶,那么 2 个瓶子最多一共试验2n就知道知道。如果 n 不是一个完全平方数,应用类似的规则,O(n)试验就可以知道结果。


2. k 个瓶子的情形

同样不失一般性,设n是个完全 k 次方数,第1个瓶子在 t(nk1k) 高度尝试,于是第 1 个瓶子尝试的次数最多是2nnk1k次。下面我们关注的横档区间长度至多是 nk1k ,然后扔第 2 个瓶子,尝试次数最多是2n1k次,最后所有的尝试次数最多是 k(n1k)=kn1k ,于是 fk(n)=O(kn1k)

另外, limnfk(n)fk1(n)=0 ,可见该算法优良。

此种算法最优原因是 fk=d1+d2+d3+...+dk1+nd1d2d3...dk1knk ,当且仅当 d1=d2=d3=...=dk=nk 时,上述不等式等号成立,f_k取得最小值。


3.额外的仅限于 2 个瓶子的算法

两个瓶子的情形下,求满足d(d+1)2n d(d>0) 的最小值。

1 个瓶子第1次在 d 阶落下,若没摔碎,第2次在 d+(d+1) 阶落下,若仍然没摔碎,第 3 次在d+(d+1)+(d+2)阶落下,依次类推…若第 1 个瓶子摔碎,则第2个瓶子从第 1 个瓶子未摔碎的最高阶依次加1阶进行测试,最差情况下总共只需 d 次即可测出不摔碎的最高阶数,依然服从O(n)级别,不过优于第 1 种算法。


讲人话


1.两个瓶子,n=100

第一个瓶子从10阶开始,每次加10阶,即10阶,20阶,30阶,40阶这样子扔,直到摔碎(最多扔10次)。

假设第一个瓶子在30阶没摔碎,在40阶摔碎了,那么结果一定介于30阶~40阶之间。那么用第二个瓶子从31阶开始,每次加1阶,31阶,32阶,33阶这样子扔,直到摔碎(也是最多扔10次)。

所以最坏结果是第一个瓶子10阶~90阶都没碎,100阶碎了,第二个瓶子91阶~99阶没碎,100阶碎了,总共20次(2100


2.k=4个瓶子,n=10000

第一个瓶子从1000阶开始,每次加1000阶,即1000阶,2000阶,3000阶,4000阶这样子扔,直到摔碎(最多扔10次)。

假设第一个瓶子在3000阶没摔碎,在4000阶摔碎了,那么结果一定介于3000阶~4000阶之间。那么用第二个瓶子从3100阶开始,每次加100阶,3100阶,3200阶,3300阶这样子扔,直到摔碎(也是最多扔10次)。

假设第二个瓶子在3700阶没摔碎,在3800阶摔碎了,那么结果一定介于3700阶~3800阶之间。那么用第三个瓶子从3710阶开始,每次加10阶,3710阶,3720阶,3730阶这样子扔,直到摔碎(依然最多扔10次)。

假设第三个瓶子在3750阶没摔碎,在3760阶摔碎了,那么结果一定介于3750阶~3760阶之间。那么用第四个瓶子从3751阶开始,每次加1阶,3751阶,3752阶,3753阶这样子扔,直到摔碎(也是最多扔10次)。

所以最坏结果是第一个瓶子1000阶~9000阶都没碎,10000阶碎了,第二个瓶子9100阶~9900阶没碎,10000阶碎了,第三个瓶子9910阶~9990阶没碎,10000阶碎了,第四个瓶子9991阶~9999阶没碎,10000阶碎了,总共40次( 4100004


3.两个瓶子,n=100

求满足 d(d+1)2n d(d>0) 的最小值。解得 d=14

第一个瓶子从14阶开始,每次增加的阶数减1,初始增加的阶数为14,即14阶,14+13阶,14+13+12阶,14+13+12+11阶,直到摔碎(理论上最多要14次(14+13+…+1=105),实际上最多仅要12次(14+13+…+3=102),我们视n=105,暂且按理论值14次算)

假设第一个瓶子(测试了6次)在60阶(14+13+12+11+10)没碎,在69阶(14+13+12+11+10+9)碎了,那么结果一定介于60阶~69阶之间。那么用第二个瓶子从61阶开始,每次加1阶,即61阶,62阶,63阶,直到摔碎(最多9次)

这种算法与第一种算法不一样在于其第一个瓶子的每次增加的。总的次数加起来不大于d=14次。


上述情况有些细节(比如最坏情况下不用每次瓶子都扔一次10000阶,因为第一个瓶子碎在10000阶我们已经知道10000阶会碎)产生的多余的1、2次的次数不要去计较0.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值