hihoCoder之hiho一下 第六十九周 解題
題目1 : HIHODrinking Game
時間限制:10000ms
單點時限:1000ms
記憶體限制:256MB
Little Hi and Little Ho are playing adrinking game called HIHO. The game comprises N rounds. Each round, Little Hipours
T milliliter of water into Little Ho's cup then Little Ho rolls a K-facesdice to get a random number d among 1 to K. If the remaining water in LittleHo's cup is less than or equal to d milliliter Little Hi gets one score andLittle Ho drinks up the remaining
water, otherwise Little Ho gets one score andLittle Ho drinks exactly d milliliter of water from his cup. After N rounds whohas the most scores wins.Here comes the problem. If Little Ho can predict thenumber d of N rounds in the game what is the minimum value
of T that makesLittle Ho the winner? You may assume that no matter how much water is added, LittleHo's cup would never be full.
輸入The firstline contains N(1 <= N <= 100000, N is odd) and K(1 <= K <=100000).The second line contains N numbers, Little Ho's predicted number d of Nrounds.
輸出Output theminimum value of T that makes Little Ho the winner.
樣例輸入
5 6
3 6 6 2 1
樣例輸出
4
解題思路:
該題的目的是要求取出最小的T,並且K的序列以及得分的規則是已知的。因而可以很容易寫出每一個輪迴中
因此,可以假設:
score = f(T)
而要證明f(T)
我們設s[i]
,r[i]
表示第i輪開始,還沒有新增 T 單位飲料時,小Ho的得分和剩餘飲料的體積;s'[i]
,r'[i]
表示第i輪開始,還沒有新增 T' 單位飲料時,小Ho的得分和剩餘飲料的體積。
我們要證明:對於i
= 1..N+1,都有s[i]
≤ s'[i]
且r[i] ≤ r'[i]
。
利用數學歸納法,i
= 1 時,s[i]
= s'[i] = 0
,r[i] = r'[i] = 0
,結論成立。
假設i
= n 時結論成立,那麼當i
= n+1 時:r[n+1]
= max(r[n]+T-d, 0)
,r'[n+1] = max(r'[n]+T'-d, 0)
。
由於r[n] ≤ r'[n]
,T < T',所以r[n]+T
< r'[n]+T'
- 當
d < r[n]+T < r'[n]+T
時,r[n+1] = r[n]+T-d
,r'[n+1] = r'[n]+T'-d
,s[n+1] = s[n]+1
,s'[n+1] = s'[n]+1
,易知結論成立; - 當
r[n]+T ≤ d < r'[n]+T
時,r[n+1] = 0
,r'[n+1] = r'[n]+T'-d > 0
,s[n+1] = s[n]
,s'[n+1] = s'[n]+1
,易知結論成立; - 當
r[n]+T < r'[n]+T ≤ d
時,r[n+1] = r'[n] = 0
,s[n+1] = s[n]
,s'[n+1] = s'[n]
,易知結論成立。
綜上所述,對於i
= 1..N+1,都有s[i]
≤ s'[i]
且r[i] ≤ r'[i]
。而f(T)
= s[N+1] ≤ s'[N+1] = f(T')
,所以函式f(T)
是單調遞增的。
f(T)
是單調遞增的,那麼,我們就可以用二分法求解了,這樣演算法複雜度降低很多。
<span style="color:#333333;">#include<iostream>
using namespace std;
int main(){
int N;
int K;
int T;
int flag=0;
cin>>N>>K;
int d[100000]={0};
int min=100000;
int max=0;
int mid=0;
for(int i=0;i<N;i++){
cin>>d[i];
if(min>d[i])
min=d[i];
if(max<d[i])
max=d[i];
}
if(min==max){ //</span><span style="color:#ff0000;">此處需要注意,當出現min與max相同時,是不會進入while迴圈的,此時T</span><span style="color:#333333;">
max++; //</span><span style="color:#ff0000;">應為max+1</span><span style="color:#333333;">
T=max;
}
else{
max++;
while(min+1<max){
mid=(min+max)/2;
T=mid;
int score_O=0;
int height=0;
for(int i=0;i<N;i++){
height+=T;
if(height<=d[i]){
height=0;
}
else{
score_O++;
height-=d[i];
}
}
if(score_O<=N/2){
min=mid;
}
else{
max=mid;
}
}
}
T=max;
cout<<T;
return 0;
//delete []d;
}</span>