1. 程式人生 > >[uva 10934] Dropping water balloons

[uva 10934] Dropping water balloons

題意:n層樓樓房,有K個水球,每個水球都有一個相同的扛摔係數。即從某層樓高及其以下的樓層摔下不會壞,而從其以上的樓層摔下會壞。問:最少需要多少次嘗試能夠求得扛摔係數

更簡單的抽象:現在有一個未知數X,範圍在1-n內。現在需要猜至少多少次Y,返回的結果是Y<X或Y>X或Y=X,則可以求出X

我們定義dp[i]為:猜測 i 次後能夠得到的最大區間

那麼有如下幾種情況:

A:第 i 次返回Y<X,這種情況對dp[i]的貢獻為:dp[i-1]

B:第 i 次返回Y>X,這種情況對dp[i]的貢獻為:dp[i-1]

C:第 i 次返回Y=X,這種情況對dp[i]的貢獻為:1

所以,dp[i] = 2 * dp[i-1] + 1

根據上述,定義dp[i][j]為猜測 i 次,得到 j 次 Y>X 回答後遊戲結束時,能夠得到的最大區間

即有:dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + 1

要求的答案為:dp[i][k] >= n中的最小的 i

一開始覺得可能會有精度問題:如果在某個加法過程中越界long long會怎麼樣,又沒法知道那麼大資料的結果是否正確,但是樣例有兩個這種大資料避免了這個想法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cstdlib>
using namespace std;

long long n,dp[150][150];

int main()
{
    int i,j,k;
    while(scanf("%d%lld",&k,&n)&&k){
        memset(dp,0,sizeof(dp));
        int flag=0;
        for(i=1;i<=63;i++){
            for(j=1;j<=k;j++)
                dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+1;
            if (dp[i][k]>=n){
                flag=1;
                break;
            }
        }
        if (flag)
            printf("%d\n",i);
        else
            puts("More than 63 trials needed.");
    }
    return 0;
}