百层高楼+扔棋子

来源:互联网 发布:梦龙网络计划是什么 编辑:程序博客网 时间:2024/05/02 04:22

 一道面试题

转自:http://zgd1st.blogbus.com/logs/6143417.html

有一个100层高的大厦,你手中有两枚相同的玻璃棋子。从这个大厦的某一层扔下围棋子就会碎。用你手中的这两枚围棋子,找出一个最优的策略,来得知那个“临界”层面——
    第一次应该从哪层开始扔?
    以你的方案,最坏的情况多少次可以测出临界层?
    这是一道Google的面试试题,具体来源不得而知,网上有无数解法,讽刺的是,Google自己搜到的大部分解法都是错的。3月份的《程序员》杂志刊登了这到题目,但我分析了一下,对杂志上给出的答案(起始测试层)也有疑问。这并不是什么了不得的难题吧(////),网上的答案集中在19次,18 次,16次和15次,我现在找到的策略是14次。我敢说超过15次的策略一定不是最优的,那么14一 是不是最优的呢?呵呵,我们来分析一下。
    假设你从50层开始扔第一枚棋子。如果第一枚棋子碎了,你就要从第1层开始逐层试探,最坏的情况是临界层在第49层,这样你总共测试了49+1=50次;如果第一枚棋子没碎,你可以把它拿到——比如说——75层,再试,如果这次碎了,另一枚棋子就要从51层试验到74层,这样总共试验了2+ (74-51+1)=26次……以此类推,总之,最坏的情况,你要试验50次。
    现在假设你从10层开始扔第一枚棋子,假如第一枚棋子没有碎,则之后每10层扔一次。跟上面相同的道理,假如临界层在第87层,总共经历了9+(87-81+1)=16次试验;最坏的情况当然是临界层在第99层,你要试验10+(99-91+1)=19次。
    显而易见,如何把大楼“分段”成为解决问题的关键。“段”分得合理,就可以让试验次数减少。那么,是让每段包含的层数均匀分布好一些,还是让投掷次数分布均匀好一些呢?如果是前者,平均分段后那么19次就是最优策略了。如果是后者,首先的解决方案是:尝试逐渐减少分段所包含的层数(否则随着第一枚棋子测试层数的累加,最坏的情况下总的投掷次数也有所增加),我们假设第一次扔棋子的层数为n,之后逐层递减,可以考虑这样一个不等式:
    n+(n-1)+(n-2)+...+2+1>=100
    也就是:
    n(n+1)/2>=100
    n^2+n>=200
    可以得到(取整数)
    n>=14
    于是就有了我们的方案:从第14层开扔第一枚棋子,如果它没有破碎,则从第14+13=27层开始扔,还是没有破碎就从14+13+12=39层开始扔,以此类推;如果第一枚棋子39层破碎了,则以第二枚棋子从第28层试验到第38层,总共试验次数为3+(38-28+1)=14次。
    按照这个策略,可测试到第14+13+12+...+4=99层。假如第99层还没有破碎,那么临界层就是第100层,总共测试了11次。如果99破碎了,那么分别在第96,97,98层用第二枚棋子进行第12,13,14次投掷(第10次投掷第一枚棋子在95层),最坏的情况是98层破碎,总共试验次数也是14次。