zoukankan      html  css  js  c++  java
  • 高楼扔玻璃球问题

    题目描述:

    腾讯大厦有100层,你手里有两颗玻璃球。当你拿着玻璃球在某一层往下扔的时候,一定会有两个结果,玻璃球碎了或者没碎。

    大厦有个临界楼层。低于它的楼层,往下扔玻璃球,玻璃球不会碎,等于或高于它的楼层,扔下玻璃球,玻璃球一定会碎。玻璃球碎了就不能再扔。

    现在让你设计一种方式,使得在该方式下,最坏的情况扔的次数比其他任何方式最坏的次数都少。也就是设计一种最有效的方式。


    两种思路解法:


    分区思想:

    ♦玻璃球属于消耗品,一旦第一颗球摔碎了,那么就只会剩下最后一颗球来去测量临界值,假设我们从第一层开始扔,那么最坏情况是从第一层试验到九十九层(最后一层就不用在测了),那么也需要试验99次

    次,因此我们不应该从第一层开始试验

    ♦假设我们从任意一层楼x层将玻璃球扔下去,球分碎和不碎两种情况,如果碎了,那么就从该层楼继续往上扔,最坏需要(100-x-1(最后一层楼不用测临界值就是它了)+1(第一颗玻璃球碎的那一次))次,

    如果没碎的话,那么继续把第一颗球从比x楼层高的y层扔,又分碎和没碎两种情况,知道第一颗球碎了,再讲第二颗球从上一次扔第一颗球没碎的楼层开始,逐层往上扔,从而找到临界值

    因此x,y的划分仍然需要我们讲究区域的划分

    ♦现在我们自己进行区间划分,假设我们将区建设为10,那么1到100层就需要划分10个区间,从最底层的区间开始逐个往上试验(每次都试该区间的最高层)一旦球在

    哪一个区间碎了,那么就可以锁定临界值在此区间,因此最坏情况为9+9(前九个区间+最后一个区间的前九层),

    但是这样做的话,仍然不是很合理?因为按照概率来算:越往高层,球碎的概率就越大,也就是说前面区间划分的不是很均匀,越往高层时,高层区间大小应该越来越小,而底层区间由于球碎的可能性

    较小,所以应该尽可能让区间大小变大,这样最终的结果:区间个数+最后一层区间的大小的值就会尽可能的变小

    我们采取逐步递减的方式,让最后一个区间只有一层,那么倒数第二个区间就只有两层,就转变成了1+2+...+x=100,解得:x约等于14,1+...+14=105,因此最大实验次数不应该超过14

    ♦以此类推,若楼层为n层,那么问题就转变为从1+...+x=n,解得的x即为最坏的次数


    动态规划思想:

    class Main{
        public static void main(String[] args) {
            int building = 100;
            //初始化,考虑数组边界0
            int[] dp = new int[building+1];
            //根据上面的思路,假设每一层都有碎的可能性,遍历求解,假设第i层球碎
            for (int i = 2;i <=building;i++){
                //最坏次数里面最优解法,假设为building,当然building-1更贴切,但并不影响程序结果
                int Min = building;//每一次i层碎的情况引发后续的 最小次数不同,需要重置Min的次数
                //第二层遍历,假设在第j层球碎
                for (int j = 1;j < i;j++){
                    //那么用到的最大次数,要么从i层开始从上往下数到j层(i-j)+1(原来的第一次在i层碎的那一次),
                    // 要么从第1层开始到j层,即用了j-1+1=j次
                    int Max = dp[i-j]+1;
                    //因为要考虑最坏情况,所以要取最大值
                    if (Max < j){
                        Max = j;
                    }
                    //Min当然要取最小值了
                    if (Max < Min){
                        Min = Max;
                    }
                }
                //第一次在i层碎的之后,后续个种情况的最小次数
                dp[i] = Min;
            }
            //遍历各种在i层碎的可能情况
            System.out.println(dp[building]);
        }
    }
  • 相关阅读:
    AI ResNet V1
    Lua基础
    git命令小结
    定时器及时间轮
    expect
    vscode 常用快捷键
    动态链接库与共享内存:
    container_of机制
    ELF文件格式
    git学习补充
  • 原文地址:https://www.cnblogs.com/hetaoyuan/p/11284546.html
Copyright © 2011-2022 走看看