1. 程式人生 > >[百度面試題]100層樓,球可能會在某一層樓摔壞,問用2個球,最壞情況下幾次測試可以找出該樓層

[百度面試題]100層樓,球可能會在某一層樓摔壞,問用2個球,最壞情況下幾次測試可以找出該樓層

該題還可以擴充套件,比如說給更多的球,如3個球,多少次測試可以找出樓層。

分析如下:

用動態規劃解這個問題

設f(a, b)為a個球做b次測試可以測試到的樓層數,可以確定的樓層數即為f(a, b) + 1,因為第1層不需測試,需要測試的樓層號僅僅為[2, f(a, b) + 1]共f(a, b)層,也就是a個球b次測試可以測試到的樓層數。考慮第1次測試,測試的樓層記為x:

1)如果球破了,就需要測試x下面的樓層,還剩下a-1個球b-1次測試,測試的樓層數為f(a - 1, b - 1)。

2)如果球沒有破,那麼需要測試x上面的樓層,還剩下a個球b-1次測試,測試的樓層數為f(a, b - 1)。

a個球b次測試為1)2)測試的樓層數及第1次測試了的1層,所以:

f(a, b) = f(a - 1, b - 1) + f(a, b - 1) + 1                                              (1)

考慮初始條件,顯然f(a, 1) = 1(a >= 1,1次測試可以測試到的樓層數當然為1,不論多少個球),f(1, b) = b(b >= 1,1個球做了b次測試當然測試到了b層樓)。

強調一下:注意f(a, b)為測試到的樓層數,f(a, b)加上不需測試的樓層才是可以確定的樓層(f(a, b) + 1)。

動態規劃解(1)式即可。

一般來說,a >= 2(1個球意義不大),可以計算出f(2, 64) = 2080,f(3, 64) = 43744,f(4, 64) = 679120。

程式如下

  1. /* 
  2.  * a balls, n floors, want to find the minimum number of floor 
  3.  * where a ball drops will be broken. output the minimum number 
  4.  * of drops 
  5.  * METHOD: dynamic programming 
  6.  * assum the answer is b, that is the number of drops
     
  7.  * f(a, b): the maximum number of floors, when a balls and b drops 
  8.  * f(a, b) = 1 + f(a, b - 1) + f(a - 1, b - 1) 
  9.  * obviously, f(a, 1) = 1; f(1, b) = b 
  10.  */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <assert.h>
  14. #include <string.h>
  15. #define DEBUG
  16. #define MAX_B 64
  17. #define MAX_A 16
  18. #define f(a, b) ff[a - 1][b - 1]
  19. static unsigned int a, n;  
  20. static unsigned longlong ff[MAX_A][MAX_B];  
  21. staticvoid init()  
  22. {  
  23.     int i;  
  24.     memset(ff, 0, sizeof(ff));  
  25.     /*f(a, 1) = 1*/
  26.     for (i = 1; i <= MAX_A; i++){  
  27.         f(i, 1) = 1;  
  28.     }  
  29.     /*f(1, b) = b + 1*/
  30.     for (i = 1; i <= MAX_B; i++){  
  31.         f(1, i) = i;  
  32.     }  
  33. }  
  34. static unsigned longlong do_find_min_drops(int i, int j)  
  35. {  
  36.     if (f(i, j))  
  37.         return f(i, j);  
  38.     f(i, j) = do_find_min_drops(i - 1, j - 1) +   
  39.         do_find_min_drops(i, j - 1) + 1;  
  40.     return f(i, j);  
  41. }  
  42. staticvoid do_print_drops(int i, int j, unsigned longlong min,   
  43.         unsigned longlong max)  
  44. {  
  45.     if (min > max)  
  46.         return;  
  47.     if (1 == i){  
  48.         assert(j == max - min + 1);  
  49.         for (i = min; i <= max; i++){  
  50.             printf("%5d", i);  
  51.         }  
  52.         printf("/n");  
  53.         printf("*************/n");  
  54.         return;  
  55.     }  
  56.     if (1 == j){  
  57.         assert(min == max);  
  58.         printf("%5lld/n", max);  
  59.         printf("*************/n");  
  60.         return;  
  61.     }  
  62.     printf("%5lld", min + f(i - 1, j - 1));  
  63.     do_print_drops(i - 1, j - 1, min, min + f(i - 1, j - 1) - 1);  
  64.     do_print_drops(i, j - 1, min + f(i - 1, j - 1) + 1, max);  
  65. }  
  66. staticvoid print_drops(int ans)  
  67. {  
  68.     do_print_drops(a, ans, 2, n);/*[2..n]*/
  69. }  
  70. staticvoid find_min_drops()  
  71. {  
  72.     /*NOTE: number of floors are [1, n]*/
  73.     int i, j, m;          
  74.     int ans;  
  75. #if 0//def DEBUG
  76.     for (i = 2; i <= MAX_A; i++){  
  77.         for (j = 2; j <= MAX_B; j++){  
  78.             printf("f(%d, %d) = %lld/n", i, j, do_find_min_drops(i, j));  
  79.         }  
  80.         printf("****************/n");  
  81.     }  
  82. #endif
  83.     i = 1;   
  84.     j = MAX_B;  
  85.     while (i <= j){  
  86.         m = (i + j) / 2;  
  87.         if (do_find_min_drops(a, m) + 1 < n)  
  88.         /* 
  89.          * why +1? because the 1st floor need not to test 
  90.          */
  91.             i = m + 1;  
  92.         else
  93.             j = m - 1;  
  94.     }  
  95.     ans = i;  
  96.     if (ans > MAX_B){  
  97.         printf("the number of the maximum drops(MAX_B = %d) is too small/n", MAX_B);  
  98.         printf("maximum floors "
  99.                 "can be tested is f(%d, %d) + 1 = %lld + 1. STOP/n", a, MAX_B, f(a, MAX_B));  
  100.         exit(0);  
  101.     }  
  102.     printf("the minimum drops: %d/n", ans);  
  103.     print_drops(ans);  
  104. #ifdef DEBUG
  105.     for (i = 1; i <= a; i++){  
  106.         for (j = 1; j <= ans; j++){  
  107.             printf("f(%d, %d) = %lld/n", i, j, f(i, j));  
  108.         }  
  109.         printf("****************/n");  
  110.     }  
  111. #endif
  112. }  
  113. int main(int argc, char **argv)  
  114. {  
  115.     if (3 != argc){  
  116.         fprintf(stderr, "usage: %s a n/n", argv[0]);  
  117.         exit(-1);  
  118.     }  
  119.     a = atoi(argv[1]);  
  120.     n = atoi(argv[2]);  
  121.     printf("a = %d/tn = %d/n", a, n);  
  122.     assert(a > 0 && a < MAX_A && n > 0);  
  123.     init();  
  124.     find_min_drops(); /*drops: 1*/
  125.     return 0;  
  126. }  

這裡,我採用遞迴的方法打出了測試過程,解釋如下:

1)2個球,100層樓時,可以計算出

f(2, 13) = 91

f(2, 14) = 105

因此需要的測試次數為14,測試過程為

   15    2    3    4    5    6    7    8    9   10   11   12   13   14

*************

   28   16   17   18   19   20   21   22   23   24   25   26   27

*************

   40   29   30   31   32   33   34   35   36   37   38   39

*************

   51   41   42   43   44   45   46   47   48   49   50

*************

   61   52   53   54   55   56   57   58   59   60

*************

   70   62   63   64   65   66   67   68   69

*************

   78   71   72   73   74   75   76   77

*************

   85   79   80   81   82   83   84

*************

   91   86   87   88   89   90

*************

   96   92   93   94   95

*************

  100   97   98   99

*************

第1次測試為15層,如果球破了,則剩下的一個球測試[2, 14],總共的測試次數最多為1+13=14 如果球沒破,則測試28層,如果破了,剩下的一個球測試[16, 27],總共的測試次數最多為1+1+12 = 14 ... 如果球沒破,測試100層,如果破了,剩下的一個球測試[97, 99],總共的測試次數最多為1{11} + 3 = 14 如果球沒破,則不存在樓層使得球可以摔破。 2)3個球,100層樓,可以計算出 f(3, 8) = 92 f(3, 9) = 129 因此測試測試最多為9次。測試過程:    38    9    2    3    4    5    6    7    8 第1個球測試38層,如果破了,第2個球測試9層,如果還破了,剩下的一個球測試[2, 8]層,總共的測試次數2 + 7 = 9 *************    16   10   11   12   13   14   15 如果第2個球沒破,則測試16層,如果破了,第3個球測試[10, 15],總共的測試測試3 + 6 = 9 *************    22   17   18   19   20   21 如果第2個球沒破,則測試22層,如果破了,第3個球測試[17, 21],總共的測試測試4 + 5 = 9 *************    27   23   24   25   26 如果第2個球沒破,則測試27層,如果破了,第3個球測試[23, 26],總共的測試測試5 + 4 = 9 *************    31   28   29   30 如果第2個球沒破,則測試31層,如果破了,第3個球測試[28, 30],總共的測試測試6 + 3 = 9 *************    34   32   33 *************    36   35 *************    37 *************    67   45   39   40   41   42   43   44 如果第1個球沒破,則測試67層,如果破了,第2個球測試45層,如果破了,第3個球測試[39, 44],總共的測試次數3 + 6 = 9。以下類似,不再重複。 *************    51   46   47   48   49   50 *************    56   52   53   54   55 *************    60   57   58   59 *************    63   61   62 *************    65   64 *************    66 *************    89   73   68   69   70   71   72 *************    78   74   75   76   77 *************    82   79   80   81 *************    85   83   84 *************    87   86 *************    88 *************   105   94   90   91   92   93 *************    98   95   96   97 *************   101   99  100 *************   103  102 *************   104 ************* 3)對於更多球的情況,輸出的測試方法分析起來有些麻煩,但是上面的動態規劃法求出的結果就容易理解了,且是保證正確的。

相關推薦

試題100可能2情況測試可以樓層

該題還可以擴充套件,比如說給更多的球,如3個球,多少次測試可以找出樓層。 分析如下: 用動態規劃解這個問題 設f(a, b)為a個球做b次測試可以測試到的樓層數,可以確定的樓層數即為f(a, b) + 1,因為第1層不需測試,需要測試的樓層號僅僅為[2, f(a, b) +

[試題]100丟玻璃球問題

轉自 : http://blog.csdn.net/prstaxy/article/details/8655988 有一棟100層高的大樓,給你兩個完全相同的玻璃球。假設從某一層開始,丟下玻璃球會摔碎。那麼怎麼利用手中的兩個球,用什麼最優策略知道這個臨界的層是第幾層??

試題(2018.10.29) 內容生態事業部

介紹自己的專案 專案的資料量有多大 zookeeper在follower死掉後,如何重新選舉? hdfs的資料儲存和讀取過程? hdfs在資料儲存過程中,如何保證副本的資料一致性? 當時我沒想起來,於是被問道,如果是你設計,你會如何實現hdf

試題陣列中出現次數超過一半的數

現在有一個數組,已知一個數出現的次數超過了一半,請用O(n)的複雜度的演算法找出這個數。 Thinking……/>/> Thinking……/>/>/> Thinking……/>/>/> Thinking……/>/>/> Think

隨機數——試題

題目如下:   已知一隨機發生器,產生0的概率是p,產生1的概率是1-p,現在要你構造一個發生器,使得它構造0和1的概率均為1/2;構造一個發生器,使得它構造1、2、3的概率均為1/3;...,構造一個發生器,使得它構造1、2、3、...n的概率均為1/n,要求複雜度最低。

js試題

小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 說出以下程式碼執行結果 var a = {n: 1} var b = a; a.x = a

試題 字串中單詞的逆轉即將單詞出現的順序進行逆轉

#include<stdio.h> #include<string.h> void Rotate(char *start,char *end) { if(start == NULL || end == NULL) return ; while(sta

試題之二叉樹層次遍歷(從上到到上)

1.二叉樹的層次遍歷 遞迴解法 class Node(object): def __init__(self, v, left=None, right=None): self.value = v self.left = l

陣列中只出現的兩數字(試題

題目要求: 在一個數組中,其餘數字都是成堆出現的,只有兩個數字出現了一次。儘快找到這兩個數字。 思路: 之前有過類似題,是一組陣列中只有一個數字出現了一次,其餘數字都是成對出現的。找到這個數字。這道題

試題:自己實現strlen,考慮32位,64位機器,考慮效能

沒辦法, 現在的大公司面試就面這個, 你不得不研究下底層的實現.要點:1) 字長邊界對齊以便加快速度. 對齊時也要考慮機器的位數哦. 2) 一次測試4個(或者8個)位元組中是否含零的技巧. 3) 需要自適應32bit/64bit機器.     定義magic變數是要使用lo

【校招】試題-4種陣列去重的方法

第一部分原文連結:http://blog.csdn.net/u011277123/article/details/54091442第二部分原文連結:http://blog.csdn.net/icessunt/article/details/69098474方法一: findI

試題:一個單鏈表,長度未知,如何快速的位於中間的那個元素

問題: 一個單鏈表,長度未知,如何快速的找出位於中間的那個元素? 設定兩個指標,p1,p2, 開始p1,p2均位於連結的頭部。 p1 每次步進兩步, p2 每次步進一步 當p1到達連結串列的末尾時,p2所在的位置就是連結串列的中間元素 時間複雜度為O(n) 詳

試題——簡單運算

問題:要求不使用+ - * / < >運算子號判定給定兩個非零數的大小。輸入:多組輸入兩個數a和b。輸出:輸出min=較小的數字,max=較大的數字實現程式碼:#include <stdio.h>int main(int argc,char* argv

試題之 啟動執行緒方式有哪執行緒池有哪

1、啟動執行緒方式: 要啟動的可以分為兩類:返回結果和不返回結果。對於這兩種,也分別有兩種啟動執行緒的方式: 1)繼承Thread類,implements Runnable介面 2)實現Callable介面通過FutureTask包裝器來建立Thread執行緒、使用Ex

試題--度度熊想去商場買頂帽子商場裡有N頂帽子有些帽子的價格可能相同度度熊想買頂價格第三便宜的帽子第三便宜的帽子價格是多少?

第一種方法:可以使用LIst 進行每次加入時進行判斷是否包含,將重複的資料不再加入List中 最後再找出List中第三便宜的帽子,若list的size小於3輸出-1;       特點:每次加入資料

二叉樹系列——二叉樹的大距離(即相距遠的兩葉子節點程式設計之美試題

來自於程式設計之美3.8。 題目:如果我們把二叉樹看做圖,父子節點之間的連線看成是雙向的,我們姑且定義“距離”為兩個節點之間邊的個數。寫一個程式求一棵二叉樹中相距最遠的兩個節點之間的距離。 如下圖所

試題——摸黑白

上網查資料的時候偶然間看到一道百度的面試題,題意大概如下: 一個桶,100個黑球100個白球,每次取走兩個球,如果同色則放入一個黑球,如果異色則放入一個白球。求最後只剩下一個黑球的概率。 思考過程: 一、首先排除了計算機模擬的思路,因為最後答案要求的概率,計算機模擬出的都是

從一道試題到分析輸入url到頁面返回的過程(或者查詢返回過程)

輸入地址瀏覽器查詢域名的 IP 地址 這一步包括 DNS 具體的查詢過程,包括:瀏覽器快取->系統快取->路由器快取...瀏覽器向 web 伺服器傳送一個 HTTP 請求伺服器的永久重定向響應(從 http://example.com 到 http://www

試題 求字串中不含重複字元的長子串長度

#include<iostream> #include<string> using namespace std; void MaxNoRepeatStrLength(string a) { unsigned int hashtable[128] =

試題:1000瓶水其中有瓶水有毒有10只老鼠並且只要老鼠喝了有毒的水必死。請問怎樣通過實驗有毒的那瓶水。

import java.util.Arrays; import java.lang.StringBuilder; import java.util.Scanner; public class toxicWater { public static final int waterNumber = 1000;