2018年第九屆藍橋杯 第四題:測試次數 (滿分17分)


標題:測試次數
x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,並且評定出一個耐摔指數來,之后才允許上市流通。
x星球有很多高聳入雲的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當於我們的2樓。
如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n
為了減少測試次數,從每個廠家抽樣3部手機參加測試。
某次測試的塔高為1000層,如果我們總是采用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?
請填寫這個最多測試次數。
注意:需要填寫的是一個整數,不要填寫任何多余內容。
 
令dp[i][j]為i層j個手機的最多(最優)測試次數。第一摔如何摔?每一層都可以作為第一摔。
設第一摔選在了第k層。
第一摔只能有兩種結果:碎或者不碎。
1)碎了,上面的層不再考慮,只需要在下面的層測試,手機少了一部,即 dp[k-1][j-1]
2)  沒碎,下面的層不再考慮,只需要在上面的層測試,手機還是那么多,即 dp[i-k][j]
因此,從k層開始摔,運氣最壞需要  max(dp[k-1][j-1], dp[i-k][j]) + 1 次測試
k有多種選擇,因此 最好的結果為:  dp[i][j] = min( max(dp[k-1][j-1], dp[i-k][j]) + 1 )    for k in [1, i]
 
 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int main() {
 6     const int N = 1000, M = 3;
 7     int dp[N+1][M+1] = {0};
 8     int _min;
 9 
10     for(int i=1; i<=N; i++) {
11         dp[i][1] = i;
12     }
13     for(int j=1; j<=M; j++) {
14         dp[1][j] = 1;
15     }
16 
17     for(int i=2; i<=N; i++) {
18         for(int j=2; j<=M; j++) {
19             _min = max(1,dp[i-1][j]+1); // count at 1 floor, was as initial value
20             for(int k=1; k<=i; k++) {
21                 _min = min( _min, max(dp[k-1][j-1],dp[i-k][j])+1 );
22             }
23             dp[i][j] = _min;
24         }
25     }
26     cout<<dp[N][M];    
27     return 0;
28 }
29 // dp[i][j] = min( max(dp[k-1][j-1], dp[i-k][j]) + 1 )    for k in [1, i]
初始化第一層

 

參考
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM