题目描述
在ural大学的一个教授的别墅上有一鹰巢。教授对这个鹰巢很感兴趣。经过仔细观察,他发现鹰巢中有若干枚蛋
。于是他想利用这些蛋做一个试验。测试一下蛋的坚固程度。
这些蛋应该是具有相同的坚硬度。存在一个非负整数E,如果从楼的第E层往下扔蛋,但不会破,但如果从第E+1
层(包括高于E+1层)扔,蛋就会破。你要做一组试验,来找出E。最简单的方法是一层层试。但是你有多个蛋
是,不必用笨方法,可以用更少的次数找出E。注意这里的次数都是指对你的方法的最坏情况且蛋破了就不能再
用,还有E可以取0。
如果实验到了最高层蛋还不破,则认为E取最高层的层数。
输入格式
一行,蛋的个数n和楼的层数k.n,k<=1000。(中间一个空格)
输出格式
最少实验次数。
样例输入
1 10
2 5
0
样例输出
10
3
//---------------------------------------------------------------------------------------------
分析:这题有好多算法,具体请看2004国家集训队论文"从《鹰蛋》一题浅析对动态规划算法的优化" 朱晨光.
其中有NK^2,K^2logK,Klog^2K,KlogK,和令人发指的sqrt(K)效率的算法.
本文只写比较弱的K^2logK.
显然通过二分,最多只需log2(k)+1次可以找出E.所以>log2(k)+1的N可以忽略.
这样N的级别就只有logK了.(这就是从NK^2到K^2logK的小小优化)
f[i,j]表示用i个蛋去试j层高(注意,不是第j层)的楼,最坏情况下,最少要几次.
显然f[1,i]=i,f[i,1]=1;
假设在第L层扔下蛋,碎了,那么f[i,j]=f[i-1,L-1]+1,没碎,f[i,j]=f[i,j-L]+1.
综上,f[i,j]=min{max(f[i-1,L-1],F[i,j-L])+1}
code:
const oo=100000000;
var f:array[0..1001,0..1001] of longint;
n,m,i,j,k,minx,lim:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b); exit(a);
end;
function max(a,b:longint):longint;
begin
if a<b then exit(b); exit(a);
end;
begin
while not seekeof do
begin
read(n); if n=0 then halt;
readln(m);
lim:=trunc(ln(m)/ln(2))+1;
if n>=lim then
begin
writeln(lim);
continue;
end;
fillchar(f,sizeof(f),0);
for i:=1 to n do f[i][1]:=1;u
for i:=1 to m do f[1][i]:=i;
for i:=2 to n do
for j:=2 to m do
begin
minx:=oo;
for k:=1 to j do
minx:=min(max(f[i-1,k-1],f[i,j-k])+1,minx);
f[i][j]:=minx;
end;
writeln(f[n][m]);
end;
end.