简介:
气球的硬度
借助一个n层的楼确定气球的硬度,如果气球从第f层掉下,没有摔破,说明气球的硬度至少为f;否则说明气球的硬度不超过f
给你k个气球来做实验,求出至少需要多少次才能确定气球的硬度(或者得出结论:站在最高层也摔不破)
分析:
首先让我们读懂题,看一下输入输出:
Input
输入的每一行包含多组测试,每组测试为一行。每组测试包含两个整数 k 和 n, 1 <= k <= 100 而 n 是一个 64 位的整数(没错,这栋建筑物的确很高),最后一组k=0,n=0 代表结束,这组测试不用处理。
Output
对于每次测试,输出在最糟情况下,测出水球破掉楼层的最少次数。
如果他多于63次,就输出“More than 63 trials needed.”
注意到输出的限制中有一点很重要:在最糟情况下
什么是最糟情况呢?就是气球在最高层也摔不破
那么问题就转化成了:我们用k个气球,需要多少次才能测试到这栋楼最顶层
我们先不管气球个数的限制:假设我们有无数个气球
那么最优方案一定是二分,这样需要logn次
那如果我们只有一个气球呢?
这就比较悲惨了,我们只能从第一层开始试(毕竟我们只有这一个气球,要是摔破了就GG了)
最坏情况下我们需要实验N次
前面这些都是帮助理解题目的,真正问题的求解还是需要我们设计十分巧妙的状态的:
我们把问题转换一下,变成:“给k个气球,丢j次,最多能确定第几层?”
这样,就可以用f(i, j)状态来表示第i个气球,丢j次最多确定的层数
对于f(i, j), 我们并不知道它最多可以确定第几层,
假设第一次在x层仍球,如果球破了,那么我们花费了一个球和扔了一次的费用,
我们可以知道f(i-1, j-1)可以确定的层数,那么就可以确定x=f(i-1, j-1)+1
如果在x层时如果球没有破,那么我们只花费了扔一次的费用,还剩下i个球,j-1次可以用,那么用这些可以确定的层数f(i, j-1)
由于每次扔球有两种可能性,这两种可能性又相互独立,所以我们的转移方程就长这样:
f(i,j)=f(i-1,j-1)+1+f(i,j-1)
一定要牢牢的记住了~~~
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll unsigned long long
using namespace std;
ll f[105][70];
int n;
ll k;
int main()
{
while (scanf("%d%llu",&n,&k)!=EOF&&n)
{
f[0][0]=0;
int ans=-1;
for (int j=1;j<=63;j++)
for (int i=1;i<=n&&ans==-1;i++)
{
f[i][j]=f[i-1][j-1]+1+f[i][j-1];
if (f[i][j]>=k)
{
ans=j;
break;
}
}
if (ans==-1) printf("More than 63 trials needed.\n");
else printf("%d\n",ans);
}
return 0;
}