算法(动态规划二)

问题
腾讯大厦有39层,你手里有两颗一抹一眼的玻璃珠。当你拿着玻璃珠在某一层往下扔的时候,一定会有两个结果,玻璃珠碎了或者没碎。大厦有个临界楼层。低于它的楼层,往下扔玻璃珠,玻璃珠不会碎,等于或高于它的楼层,扔下玻璃珠,玻璃珠一定会碎。玻璃珠碎了就不能再扔。现在让你设计一种方式,使得在该方式下,最坏的情况扔的次数比其他任何方式最坏的次数都少。也就是设计一种最有效的方式。

分析
咱们先不论腾讯大厦具体为多少层。假设大楼为 N 层,那么 F(N) 为 N 层大厦最坏情况的最小值。

先假设一下,在第 10 层进行了抛球:

碎了,那么寻找临界楼层,最坏情况下只需要从 1 - 9 逐一遍历,也就是 10 次。
没碎,那么寻找临界楼层,相当于转换为 F(N - 10) + 1 。其中 1 为本次。
也就是说,第 10 层的最坏情况为 max(10, F(N - 10) + 1)。

那么 F(N) = min{ max(1, F(N - 1) + 1), max(2, F(N - 2) + 1), max(3, F(N - 3) + 1), …… , max(N - 1, F(1) + 1)}

有了以上这个状态转移方程,就可以采用动态规划将其实现。

<?php
     $height = 39;
     echo getMinTimes($height);

     function getMinTimes($value)
     {
         $minTimes = []; 
         $minTimes[0] = 0;  // 如果只有0层的话最大次数为0
         $minTimes[1] = 1;  // 如果只有1层的话最大次数为1
         // 初始化参数
         for($levelOne = 2; $levelOne <= $value; $levelOne ++) {
             $min = $levelOne;
             for($levelTwo = 1; $levelTwo < $levelOne; $levelTwo ++) {
                 $tmp = max($levelTwo, $minTimes[$levelOne - $levelTwo] + 1);
                 // echo $tmp;
                 // echo "  ";
                 if ($tmp < $min) {
                    $min = $tmp;
                 }
                 // echo $min;
                 // echo "===   ";
             }
             // echo PHP_EOL;
             $minTimes[$levelOne] = $min;
             // echo $minTimes[$levelOne];
         }
         return $minTimes[$value];
     }
?>         

 

posted @ 2020-03-08 17:35  泥土里的绽放  阅读(158)  评论(0编辑  收藏  举报