uva 10934 Dropping water balloons
你有k个一模一样的水球,在一个n层楼的建筑物上进行测试,你想知道水球最低从几层楼往下丢可以让水球破掉。由于你很懒,所以你想要丢最少次水球来测出水球刚好破掉的最低楼层。(在最糟情况下,水球在顶楼也不会破)你可以在某一层楼丢下水球来测试,如果水球没破,你可以再捡起来继续用。
Input
输入的每一行包含多组测试,每组测试为一行。每组测试包含两个整数 k 和 n, 1 <= k <= 100 而 n 是一个 64 位的整数(没错,这栋建筑物的确很高),最后一组k = 0,n=0 代表结束,这组测试不用处理。
Output
对于每次测试,输出在最糟情况下,测出水球破掉楼层的最少次数。如果他多于63次,就输出“More than 63 trials needed.”
扔水球,扔手机,扔水晶球等。。。这题并不是第一次见了,这次就来分析一下解题的思路。
我们最先想到的是二分法,可二分并不是最佳的,因为本题中尝试的次数有限制,这样就不能大胆的在二分点上尝试。
所以我们可以换一种思路:
有k个气球,丢j次,最多可以确定多少层??
由此可设dp[i][j]为还剩i个气球,丢了j次后已确定的最高层数。
当dp[i][j]时气球破了,则可确定dp[i-1][j-1]+1层;若没有破,则剩下的i个气球可确定dp[i][j-1]层。
则可得:
dp[i][j]=dp[i-1][j-1]+dp[i][j-1]+1;
附AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 long long dp[110][70]; 5 6 int main(){ 7 ios::sync_with_stdio(false); 8 long long n,k; 9 memset(dp,0,sizeof(dp)); 10 for(int i=1;i<64;i++){ 11 for(int j=1;j<64;j++){ 12 dp[i][j]=dp[i-1][j-1]+dp[i][j-1]+1; 13 } 14 } 15 while(cin>>k>>n&&k&&n){ 16 int flag=0; 17 for(int i=0;i<=63;i++){ 18 if(dp[k][i]>=n){ 19 cout<<i<<endl; 20 flag=1; 21 break; 22 } 23 } 24 if(!flag){ 25 cout<<"More than 63 trials needed."<<endl; 26 } 27 } 28 return 0; 29 }