var code = "9d83351f-b3a4-4a40-928a-d6b24bbfae2f"
题目
The classic Two Glass Balls brain-teaser is often posed as:
"Given two identical glass spheres, you would like to determine the lowest floor in a 100-story building from which they will break when dropped. Assume the spheres are undamaged when dropped below this point. What is the strategy that will minimize the worst-case scenario for number of drops?"
Suppose that we had only one ball. We'd have to drop from each floor from 1 to 100 in sequence, requiring 100 drops in the worst case.
Now consider the case where we have two balls. Suppose we drop the first ball from floor n. If it breaks we're in the case where we have one ball remaining and we need to drop from floors 1 to n-1 in sequence, yielding n drops in the worst case (the first ball is dropped once, the second at most n-1 times). However, if it does not break when dropped from floor n, we have reduced the problem to dropping from floors n+1 to 100. In either case we must keep in mind that we've already used one drop. So the minimum number of drops, in the worst case, is the minimum over all n.
You will write a program to determine the minimum number of drops required, in the worst case, given B balls and an M-story building.
Input
The first line of input contains a single integer P, (1 ≤ P ≤ 1000), which is the number of data sets that follow. Each data set consists of a single line containing three(3) decimal integer values: the problem number, followed by a space, followed by the number of balls B, (1 ≤ B ≤ 50), followed by a space and the number of floors in the building M, (1 ≤ M ≤ 1000).
Output
For each data set, generate one line of output with the following values: The data set number as a decimal integer, a space, and the minimum number of drops needed for the corresponding values of B and M.
Sample
Inputcopy Outputcopy 4 1 2 10 2 2 100 3 2 300 4 25 900 1 4 2 14 3 24 4 10
大意:
有k个鸡蛋与n层高的楼,在某一层楼以上扔鸡蛋,鸡蛋会碎,求最小的实验次数(在最坏情况下),找出是哪一层楼
题解:
dp毋庸置疑,可状态千奇百怪
一个奇妙的做法,设f[i][j]为有i次操作有j个蛋能检测的楼高
如果可以求出所有f[i][j],再枚举最小的i使f[i][k]>=n,问题就迎刃而解了;
我们先考虑这个dp状态的转移
转移:
假设在第i次实验时,手上j个鸡蛋;
如果在第i次实验时,鸡蛋碎了,我们还有j-1个鸡蛋,同时还剩i-1次实验机会,(且我们知道要找的楼层在下面,(其实这个知不知道都无关紧要))
于是就有 f[i][j]+=f[i-1][j-1];
如果在第i次实验时,鸡蛋没碎,那么我们还有j个鸡蛋,同时还剩i-1次实验机会,
于是又有 f[i][j]+=f[i-1][j];
最后还知道了自己当前所处的楼层的信息,所以
f[i][j]+=1;
将上述式子合并就有了最终的状态转移方程式:
f[i][j]=f[i-1][j]+f[i-1][j-1]+1
边界:
case1:
显然,当只有一次实验机会时,在最坏情况只能检测出一层楼
所以,所有的f[1][1,2,3,4,..........]=1;
case2:
当只有一个鸡蛋时,为了保险(鸡蛋不碎),我们会一层一层的尝试,所以能实验的次数就是能检测出的高度,则f[i][1]=i;
有了以上铺垫就可以,解决这道题了
最后献上代码:
#include<iostream>
#include<cstring>
using namespace std;
int T,k,n,cas;
int f[1005][55];//第i次操作有j个蛋能检测的楼高
void init(){
memset(f,0,sizeof f);
for(int i=1;i<=k;i++) f[1][i]=1;//做一次操作只能检测一层楼
for(int i=1;i<=n;i++) f[i][1]=i;//只有一个蛋时,有几次操作就能检测几层楼
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&cas,&k,&n);
init();
int ans;
for(int i=2;i<=n;i++){
for(int j=1;j<=k;j++){
f[i][j]=1+f[i-1][j-1]+f[i-1][j];
}
if(f[i][k]>=n){
ans=i;
break;
}
}
printf("%d %d\n",cas,ans);
}
}
眼中若是倾城,便是一生中最爱