0062 玻璃珠从楼层上丢下找破碎临界楼层(腾讯笔试题)

来源:互联网 发布:SQL中trunc函数 编辑:程序博客网 时间:2024/04/29 03:20

最近做的一道腾讯笔试题,大意是:

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

思路:

动态规划。设楼层N

把问题转换为在39-N里找临界楼层。

假如结果都保存在F[40]这个数组里面,那么:
F[N]=40-N,
F[40]=min(max(1,1+F[N-1]),max(2,1+F[N-2]),……,max(N-1,1+F[1]));

已知状态转移方程,代码就简单了:

#include <iostream>  using namespace std;//gendlee 2016-9-17#define N 40int F[N]={0};void Test(){     int temp;    for (int loop1=2; loop1<N; ++loop1)   {F[loop1]=loop1;for (int loop2=1; loop2<N;++loop2)   {temp= (loop2>=(1+F[loop1-loop2]))?loop2:(1+F[loop1-loop2]);if (F[loop1]>temp)F[loop1]=temp; } }}int main(){    F[0]=0;    F[1]=1;     Test();     cout<<F[N-1]<<endl;   return 0;}


结果:9  次
那么实际是怎样操作这9次呢:

先从9楼开始抛第一次;如果没碎,再从17(9+8)楼抛第二次;如果还没碎,再从24(9+8+7)楼抛第三次;如果还没碎,再从30(9+8+7+6)楼抛第四次;如此,每次间隔的楼层少一层。这样,任何一次抛棋子碎时,都能确保最多抛9次可以找出临界楼层。 
证明如下: 
1、第一次抛棋子的楼层:最优的选择必然是间隔最大的楼层。比如,第一次如果在m层抛下棋子,以后再抛棋子时两次楼层的间隔必然不大于m层(大家可以自己用反证法简单证明) 
2、从第二次抛棋子的间隔楼层最优的选择必然比第一次间隔少一层,第三次的楼层间隔比第二次间隔少一层,如此,以后每次抛棋子楼层间隔比上一次间隔少一层。(大家不妨自己证明一下) 
3、所以,设n是第一次抛棋子的最佳楼层,则n即为满足下列不等式的最小自然数: 
  不等式如下:  1+2+3+...+(n-1)+n  >=   39 
由上式可得出  n = 9
即最优的策略是先从第9层抛下,最多抛9次肯定能找出临界楼层。

0 0