题目描述
在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.

相关文章: