问题大意:给你 n 个鸡蛋,问你在 m 层中,进行多少次投鹰蛋能确定,鹰蛋最高在哪层能不碎( 即最坏情况需要多少次 ),

如果第m层也不碎答案为m。

 

这个问题好像有个大牛写过一篇论文。我只学了其中的两个方法。

第一种方法是 log( n )*n^2,我们将状态设成 dp[ i ][ j ] 表示成有 i 个鸡蛋,层数为 j 时最少需要的实验次数。

那么我们考虑在第一次在 k 层投鹰蛋,有两种情况,一种是鹰蛋碎了 这种状况对应的子问题为dp[ i -1 ][ k-1 ](k层下面的部分),

另一种子问题是鹰蛋没碎为 dp[ i ][ m-k ](k层上面的部分),因为考虑最坏的情况,所以取两者的最大值赋给dp[ i ][ j ],并加上

第一次在k层投的一次。 对于k是哪个,只需要枚举 k 就可以了。考虑鸡蛋充足的情况,那么就是二分的方法,这样对于

i > log(j) 的状态直接赋值。

鹰蛋坚硬度实验_IT鹰蛋坚硬度实验_IT_02
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int dp[12][1005],n,m;
int main()
{
    //freopen("text2","w",stdout);
    memset(dp,inf,sizeof(dp));
    for(int i=1;i<=1000;i++) dp[1][i]=i;
    for(int i=1;i<=10;i++) dp[i][1]=1;
    for(int i=2;i<=10;i++)
    {
        for(int j=1;j<=1000;j++)
        {
            int res;
            dp[i][j]=dp[i-1][j];//这里特别注意,wa地生活不能自理。
            for(int k=1;k<=j;k++)
            {
                dp[i][j]=min(dp[i][j],max(dp[i-1][k-1]+1,dp[i][j-k]+1));
            }
        }
    }
    while(scanf("%d%d",&n,&m)!=EOF && n && m)
    {
        if(m==0)
        {
            puts("0");
            continue;
        }
        if(n>10) n=10;
        printf("%d\n",dp[n][m]);
    }
    return 0;
}
View Code

 

第二种方法是,我们考虑dp[ i ][ j ]为有 j 个鸡蛋进行 i 次能确定的最高楼层。假设在某一层楼扔下一只蛋,且碎了,

则在下面的( j - 1)次里,我们要用(i-1)个蛋在下面的层中确定 E为了使 dp(i,j)达到最大,我们当然希望下面的楼层数达到最多,

这便是一个子问题,答案为 dp[ i - 1 , j - 1 ];假设蛋没碎,则在后面( j - 1)次里,我们要用 i 个蛋在上面的楼层中确定 E,

这同样需要楼层数达到最多,便为 dp[ i - 1 , j ],然后不管怎样,我们都用了一次。即dp[ i , j ]=dp[ i - 1 , j - 1 ] + dp[ i , j - 1 ] + 1。

鹰蛋坚硬度实验_IT鹰蛋坚硬度实验_IT_02
#include<bits/stdc++.h>
using namespace std;
LL dp[1010][1010];
int main()
{
    for(int i=1;i<=1000;i++)
    {
        dp[1][i]=i;
        dp[i][1]=1;
    }
    for(int i=2;i<=1000;i++)
    {
        for(int j=2;j<=1000; j++)
        {
            dp[i][j]=dp[i][j-1]+dp[i-1][j-1]+1;
        }
    }
    int n,m;
    while(cin>>m>>n, n && m)
    {
        LL ans=-1;
        for(int i=1;i<=1000;i++)
        {
            if(dp[m][i]>=n)
            {
                ans=i;
                break;
            }
        }
        cout << ans << endl;
    }
    return 0;
}
View Code