/*SE:wn------王宁*/
前面是正解,后面的是我自己第一次尝试的代码——仅仅走出了第一步,很有借鉴意义,我也在那里做了一下总结——放在代码中的那一段注释。
/*SE:wn------王宁*/
/*T - Dropping water balloons UVA - 10934 */
#include<bits/stdc++.h>
using namespace std;
const int maxk = 100+5;
const int maxf = 63 +5;
/*表示用给定气球和给定次数能测最多几层楼*/
unsigned long long d[maxk][maxf];
unsigned long long n;
int k,i,j,ans;
int main()
{
memset(d,0,sizeof(d));
for(i=1;i<=100;i++)
for(j=1;j<=63;j++)
{
d[i][j]=1+(d[i-1][j-1])+(d[i][j-1]);
/*
这栋高楼呢,其实你并不知道有多少层也不知道一开始应该从哪扔
如果在某一层破掉了,那么下面的层数必须用 (i-1)个气球配合(j-1)次测试次数给测出来
所幸的是,我们知道 用 (i-1)个气球配合(j-1)次测试次数 最多能测几层
如果没破掉,那么用i个气球配合(j-1)次测试次数还可以再多测几层
所幸的是,我们知道 用 (i)个气球配合(j-1)次测试次数 最多能测几层
这种建楼方式像不像先造中间再往下往上造?
总之,是破和不破的两种可能性决定了最终能测的最高层数
题外话:long long int的最大值(2^63-1)刚好就是最后的那个9223372036854775807
这也是我们d的最大值——在i<=100,j<=63的情况下。
有兴趣自己可以打印出来玩玩……
*/
}
while(cin>>k>>n&&k){
int ans=-1;
for(i=1;i<=63;i++)
if(d[k][i]>=n) { ans=i;break; }
if(ans==-1) printf("More than 63 trials needed.\n");
else printf("%d\n",ans);
}
return 0;
}
—————我是美貌与智慧并存的分割线————
/*SE:wn------王宁*/
/*T - Dropping water balloons UVA - 10934 */
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100+5;
const int maxb = 7 +5;
int d[maxb][maxn];
int k,n,i,j,p,sum,ans;
int main()
{
/*之前在蓝桥杯遇到过扔杯子的题目
后来看了别人的题解,今天凭着自己理解又写出来了
但是这个存在的问题就是,楼层数很多,不可能给你开那么大的数组
想来时间开销也不够
后来看了刘汝佳大神的原码才知道他把状态给重定义了
我的状态是给定气球的数量和层数,dp值是最少需要扔几次
他则是给定气球数量和测试次数,dp值是算出最多能扔几层
知道了之后,就能利用不等式关系,在气球数目确定的情况下,
每次多给一次测试次数,找出(第一次能测的最高层数大于等于当前层数)的测试次数
这就是答案了
所以以后遇到状态值过大,目标值又很小的题目,应当尝试将状态值重新定义
*/
d[0][0]=0; //前面是气球的数量,后面是层数
for(i=1;i<maxn;i++) d[1][i]=i;
for(i=1;i<maxb;i++) d[i][0]=0;
for(i=2;i<maxb;i++)
for(j=1;j<maxn;j++){
d[i][j]=1000000;
for(p=1;p<=j;p++){
ans=-1;
ans=max(ans,d[i][j-p]+1);
ans=max(ans,d[i-1][p-1]+1);
d[i][j]=min(d[i][j],ans);
}
}
printf("%d",d[2][100]);
return 0;
}