1. 程式人生 > >2018藍橋杯 省賽D題(測試次數)

2018藍橋杯 省賽D題(測試次數)

list 需要 拓展 解釋 pan 大廠 測試 當前 con

x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,並且評定出一個耐摔指數來,之後才允許上市流通。
x星球有很多高聳入雲的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當於我們的2樓。
如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n
為了減少測試次數,從每個廠家抽樣3部手機參加測試。
某次測試的塔高為1000層,如果我們總是采用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?

請填寫這個最多測試次數。
註意:需要填寫的是一個整數,不要填寫任何多余內容。

思路:這裏有兩種解法 動態規劃 和 手算 後一種方法比較好理解就不做解釋 主要來解決一下動態規劃

首先要理解一下dp[i][j] i表示手機數 j表示樓層數 dp[][]就表示有i部手機j層樓的情況下 最壞運氣下需要測試的次數

我們先假設不采取最佳策略 即沒一個j層的樓房 我們都要摔j次 但是當手機只有一部的情況時 這其實就是最佳策略,那麽我們就可以逐漸往上拓展

假設我們已經把 i-1部手機對於所有樓層的次數已經找出,現在我們來求有i部手機時的測試次數

為此我們需要遍歷 當前之前的樓層k(1~j-1)假設在k層摔壞 我們就選取i-1部手機對於k-1層樓房的最壞情況dp[i-1][k-1]+1

假如在k層沒有摔壞 那麽我們就可以選取i部手機對於剩下j-k層的最壞情況 dp[i][j-k]+1

由於是最壞情況 我們需要在兩者之間取最大值,但我們又是采取的最佳策略 所以對於之前的非最佳策略 我們需要取最小值,即:

dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k])+1);

最後答案為19

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string
> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define ll long long int using namespace std; inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1}; int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1}; const int inf=0x3f3f3f3f; const ll mod=1e9+7; int dp[5][1007]; int main(){ ios::sync_with_stdio(false); for(int i=1;i<=3;i++) for(int j=1;j<=1000;j++) dp[i][j]=j; for(int i=1;i<=1000;i++) for(int j=2;j<=3;j++){ for(int k=1;k<i;k++) dp[j][i]=min(dp[j][i],max(dp[j-1][k-1],dp[j][i-k])+1); } cout<<dp[3][1000]<<endl; return 0; }

2018藍橋杯 省賽D題(測試次數)