题意: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;
}