一道动态规划的笔试题

Posted 学习源笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一道动态规划的笔试题相关的知识,希望对你有一定的参考价值。


      在一些大厂的笔试环节中,经常会考一些动态规划的算法题,比如以下题目。

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


     例如:有这样一种方式,第一次选择在60层扔,若碎了,说明临界点在60层及以下楼层,这时只有一颗珠子,剩下的只能是从第一层,一层一层往上实验,最坏的情况,要实验59次,加上之前的第一次,一共60次。若没碎,则只要从61层往上试即可,最多只要试40次,加上之前一共需41次。两种情况取最多的那种。故这种方式最坏的情况要试60次。仔细分析一下。如果不碎,我还有两颗珠子,第二颗珠子会从N+1层开始试吗?很显然不会,此时大楼还剩100-N层,问题就转化为100-N的问题了。


    那该如何设计方式呢?  

    根据题意很容易写出状态转移方程:N层楼如果从n层投下玻璃珠,最坏的尝试次数是:max(n,1+F(N-n))


   那么所有层投下的最坏尝试次数的最小值即为问题的解:F(N) = min(max(1,1+F(N-1)),max(2,1+F(N-2)),...max(n,1+F(N-n)),...max(N-1,1+F(1)))。其中F(1)=1.


/*
*功能:100楼层抛珠问题
*/

#include<iostream>
using namespace std;
int dp[101];
//N<=100;
int floorThr(int N)
{
   for(int i=2;i<=N;i++)
   {
       dp[i]=i;
       for(int j=1;j<i;j++)
       {
           int tmp = max(j,1+dp[i-j]);
           if(tmp<dp[i])
               dp[i] = tmp;
       }
   }
   return dp[N];
}
int main()
{
   dp[0]=0;
   dp[1]=1;
   int dis = floorThr(100);
   cout<<dis<<endl;
   system("Pause");
}


     输出为14,说明在合适的楼层抛玻璃珠,最差情况下只需14次可找到临界层。

     答案是先从14楼开始抛第一次;如果没碎,再从27楼抛第二次;如果还没碎,再从39楼抛第三次;如果还没碎,再从50楼抛第四次;如此,每次间隔的楼层少一层。这样,任何一次抛棋子碎时,都能确保最多抛14次可以找出临界楼层。

以上是关于一道动态规划的笔试题的主要内容,如果未能解决你的问题,请参考以下文章

说一下前天腾讯实习的笔试题--字符串回文问题(动态规划)

动态规划字节跳动算法笔试遭遇雨水坑问题

一道有意思的笔试题

一道有意思的笔试题

吃鸡问题中的的动态规划

c++一道关于继承和析构的笔试题