zoukankan      html  css  js  c++  java
  • 抛玻璃算法

    下面为例子来源;

    网上闲逛,看到一算法题大体如下:

    有一幢100层高的大楼,给你两个完全相同的玻璃棋子。
    假设从某一层开始,丢下玻璃棋子就会破碎。那么怎么利用手中的两颗棋子,
    用一种什么样的最优策略,知道这个临界的层高呢?

      大致想了下... 得出的第一个算法是33  66  99 

      IF( 既第一个Q从33楼扔,如果碎了. 就从第一层向33层枚举..) 

       {

        假设最糟糕的情况是32楼是临界点.

         33楼 + 1 + 2 +3 ....... +32  =  33次...  嗯...上下楼33,累死了... 

     }

    else

      IF(33楼扔下去没碎,那么从66楼往下扔)

           最糟糕的情况又发生了 =.=!   65层才是临界点.那么...

         33层 + 66层 + (34---65)  =33次 ..............!!!  

       如果66没碎...  99也没碎.. 那么就是 33 + 66 + 99 + (67--98 ) = 34次..

     脑袋里反映出来的第一个算法,, 最糟糕的情况要扔 33或者34次..  效率显然不高..

     

    看了下回帖,有个叫IToa什么的同志... 贴出了他的算法..

       第一次从15层往下扔..碎了的话,, 最糟糕 15 + (1-13) = 14次.

      没碎继续: 第二次从(15-1)+15 = 29 层往下扔.  碎了为: 15 + 29 + (16 ---28)= 14次

             第三次 (14 - 1) + 29  = 42   碎了的话 最多也是跑上14次而已... 

       该算法最糟糕的情况为14次或者13次就能得出临界点,,效率显然比我高的多..

      毕竟. 我是菜鸟.. 哈哈哈哈

      还有的人的算法是 以10为单位扔玻璃球... 那么结果是: 10,10, 11 .12.13.14.15.16.17.18.

          显然,,15-1的这种算法比较均衡,从头到位都是13或者14... 而以10为单位的这种算法前期比较有效...

         但在临界点==99层的情况,,要测18次才行..

      而前一种算法则无论临界点在那层..都只要14次就能完成............    

          仔细思考后,,发现第一种算法仍然不是最有效的...

         10 23(10+15-2) 35(23+15-3)............ 100

       该算法扔玻璃球的效率为 10 13 13 13.........12 

       既

        int n,s,L ;

       L = 100 ; //楼层 

        n=sqrt(L) ;   //给该楼开方==10     =.=!

          s= n+ sqrt(n);  // 继续开方得到计算差值

        while(n<=L)

          {n = n + (n+s--); // 循环计算直到开关为假, >楼层数

         ................ //设置好临界点,满足临界点后标记然,退出循环; }

     

     

     到网络上搜索了一下..有段不知出处的C++代码.

     里面用暴力穷举出的最佳点是:9 22 34 45 55 64 72 79 85 90 94 97 99 100

            9为开端,偶的是10为开端... 其后都是15-(2++)

     第一部比偶的快了一点点.. 哈哈哈哈  次数是: 9 13 13 13..........12 

      但偶的算法适用于各种高度的楼层..只是两次开方,循环计算<sqrt(楼层高度)

      对方的是暴力破解... 如果楼层过高...嗯嗯,家用计算机可能需要数年才能计算出来

       

    没有最高效,只有更高效....继续学习ing..........


    【以上来自:http://blog.csdn.net/Estel/archive/2007/02/07/1504840.aspx

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1504840 

    我的解法为:

          我是这么考虑的,要采用最小的代价找出摔碎玻璃球的方法,那么首先要区分区间,即摔碎球的区间在哪儿?
    因为在每一层都有可能,那么应该是符合平均分布规律的,也就是说我们只要将区间分析正确了,那么得到应该为最佳的方案。
          只有两个球,那么我们只能先通过摔碎玻璃球来确定在哪个区间中,然后逐层往上摔球。
    接下来该分区间了,该怎么分呢?显然有以下关系式:
                                        前面区间的个数+当前区间中的数目<=某一个值M
          因此问题就转换为求出“某一个值M的问题了,因为当这个值求出之后,开始时前面区间的个数为0个,从数学上讲是一个递推的关系式。
         我们可以推测,除了首和尾之外,中间区间必然要满足:
                                      前面区间个数+当前区间中的数目=某一个值M
         设当前区间为第i个区间,那么前面有i-1个区间,而当前区间的个数为:M-i-1 (>=0),其应该满足下面一个关系式:
                                     ∑(M-i-1)<L(层数) i从1到last-1,其中i=last<M
          最佳的区间分配显然为last+1=M,即最末尾只有一个数的时候。
    由此可以推断的层数为(逆向排列):
    1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,……
           当层数为100时,(1+区间个数)*区间个数/2 < 100,即所有区间个数之和小于总的层数。
    于是计算得到区间个数为:13。
    也就是说层的个数为:
    1,2,3,4,5,6,7,8,9,10,11,12,13
    因此排列方式为:
    100,99,97,94,90,85,79,72,64,55,45,34,22,9
    至此,解答完毕!

    希望能有更好的算法(不同思想上的)……

    /*
    *
    * Copyright (c) 2011 Ubunoon.
    * All rights reserved.
    *
    * email: netubu#gmail.com replace '#' to '@'
    * http://www.cnblogs.com/ubunoon
    * 欢迎来邮件定制各类验证码识别,条码识别,图像处理等软件
    * 推荐不错的珍珠饰品,欢迎订购 * 宜臣珍珠(淡水好珍珠) */
  • 相关阅读:
    python之HtmlTestRunner(一)生成测试报告
    测试场景分析-上传文件软件
    测试场景分析-一只钢笔
    md文件的基本常用编写语法
    ipad4密码忘记锁定了如何破解
    python之unittest验证函数功能
    python之排序的几种方法
    python之导入模块的方法
    面经-蘑菇街
    面经-有赞
  • 原文地址:https://www.cnblogs.com/ubunoon/p/2058951.html
Copyright © 2011-2022 走看看