UVA 10934 Dropping water balloons (动规)

来源:互联网 发布:美丽港发型设计软件 编辑:程序博客网 时间:2024/05/01 19:06

Description

It’s frosh week, and this year your friends have decided that they would initiate the new computer science students by dropping water balloons on them. They’ve filled up a large crate of identical water balloons, ready for the event. But as fate would have it, the balloons turned out to be rather tough, and can be dropped from a height of several stories without bursting!
So your friends have sought you out for help. They plan to drop the balloons from a tall building on campus, but would like to spend as little effort as possible hauling their balloons up the stairs, so they would like to know the lowest floor from which they can drop the balloons so that they do burst.
You know the building has n floors, and your friends have given you k identical balloons which you may use (and break) during your trials to find their answer. Since you are also lazy, you would like to determine the minimum number of trials you must conduct in order to determine with absolute certainty the lowest floor from which you can drop a balloon so that it bursts (or in the worst case, that the balloons will not burst even when dropped from the top floor). A trial consists of dropping a balloon from a certain floor. If a balloon fails to burst for a trial, you can fetch it and use it again for another trial.

Input

The input consists of a number of test cases, one case per line. The data for one test case consists of two numbers k and n, 1 ≤ k ≤ 100 and a positive n that fits into a 64 bit integer (yes, it’s a very tall building). The last case has k = 0 and should not be processed.

Output

For each case of the input, print one line of output giving the minimum number of trials needed to solve the problem. If more than 63 trials are needed then print ‘More than 63 trials needed.’ instead of the number.

题意

有 k 个完全相同的水球,你想知道水球最低从几层楼扔下会使得水球破裂。由于你很懒,因此你想通过测试最少的次数来获知使水球破裂的最低楼层,当然,可能在顶楼水球也不会破。注意:如果在某层扔下使水球破了,该水球将无法再次使用。

思路

看完题面很容易就会想到二分,很遗憾这并不符合二分的要求,水球在过高的楼层落下会破裂,且水球数量有限。

再次思考,当只有一个水球时,为了知道使水球破裂的最低楼层,唯一的方案是从底层一层一层往上测试,最坏情况下的最少次数为 n (楼层总高度)。

但是,当有两个水球的时候,可以考虑用第一个水球做二分,在 n2 的层数扔下

  • 若水球未破裂,则之后从 [n2+1,n] 进行枚举
  • 若水球破裂,则之后从 [1,n21] 进行枚举

使用上述策略进行反向预处理。令 dp[i][j] 表示有 i 个水球扔 j 次能判断的最多楼层数量。

状态转移方程为 :dp[i][j]=dp[i1][j1]+dp[i][j1]+1

再对输入的 k 与 n 进行判断,当有 k 个水球时,扔 ?次能使得 dp[k][?]n

HINT: 由于扔球的上限次数为 63 ,故可知多余 63 个水球的情况等同于只有 63 个水球的情况,故不用担心预处理过大的问题。

代码

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;int k;long long n, dp[65][65];void init(){    for(int i=1;i<64;i++)    for(int j=1;j<64;j++)        dp[i][j] = dp[i][j-1] + 1 + dp[i-1][j-1];}bool solve(){    for(int i=0;i<=63;i++)        if(dp[k][i] >= n) {            printf("%d\n",i);            return true;        }    return false;}int main(){    init();    while(scanf("%d %lld",&k, &n)!=EOF && k)    {        k = min(k, 63);        if(!solve()) printf("More than 63 trials needed.\n");    }}
0 0
原创粉丝点击