UVA10934&&蓝桥杯测试次数&&鹰蛋问题

UVA10934&&蓝桥杯::测试次数&&鹰蛋问题

​ 以上三种问题都属于一种问题,这里我用鹰蛋问题为例进行分析

参考网址:http://datagenetics.com/blog/july22012/index.html

只有这篇完全诠释了我的所有问题。

我这里只讲述动态规划的解决方案。请耐心看完

f [ e ] [ k ] ​ f[e][k]​ f[e][k]代表有 e ​ e​ e 鸡蛋 k ​ k​ k 层楼 找出答案的最小测试次数。

  • 假设我这次测试时候在第 1 ​ 1​ 1 k ​ k​ k的第 i ​ i​ i 层扔鸡蛋。那么分两种情况:

    • 在第 i ​ i​ i层鸡蛋没碎,那么坚韧度在 [ i + 1 , k ] ​ [i+1,k] ​ [i+1,k]中,即在 k − i ​ k-i​ ki 个连续的层之间,现在我还有 e − 1 ​ e-1​ e1个鸡蛋,那么问题归结到 f [ e − 1 ] [ k − i ] ​ f[e-1][k-i]​ f[e1][ki], 即 f [ e ] [ k ] = f [ e − 1 ] ] [ k − i ] + 1 ​ f[e][k]=f[e-1]][k-i]+1​ f[e][k]=f[e1]][ki]+1

    • 在第 i ​ i​ i层鸡蛋没碎,那么坚韧度在 [ 1 , i − 1 ] ​ [1,i-1]​ [1,i1]之间,即在 i − 1 ​ i-1​ i1个连续的层之间,现在我还有e个鸡蛋,那么问题归结到 f [ e ] [ i − 1 ] ​ f[e][i-1]​ f[e][i1],即 f [ e ] [ k ] = f [ e ] [ i − 1 ] + 1 ​ f[e][k]=f[e][i-1]+1​ f[e][k]=f[e][i1]+1

  • 因为这个问题属于运气问题,故是不可控的,因为要求在最坏情况下,故 f [ e ] [ k ] = m a x ( f [ e − 1 ] [ i − 1 ] , f [ e ] [ k − i ] ) + 1 f[e][k]=max(f[e-1][i-1],f[e][k-i])+1 f[e][k]=max(f[e1][i1],f[e][ki])+1

上面就找出了有 e e e个鸡蛋 k k k 层楼,在第 i i i层扔鸡蛋的所需要的最小测试次数,(Remember we need to mimimize the number of drops in the worst case)

虽然运气是不可控的,但是我们选取的 i i i是可控的,所以我们可以遍历出所有的i,令 f [ e ] [ k ] f[e][k] f[e][k]选取其中最小的

递推式 f [ e ] [ k ] = m i n (   m a x ( f [ e − 1 ] [ i − 1 ] , f [ e ] [ k − i ] ) + 1 ) ) , i ∈ [ 1 , k ] f[e][k]= min({~max(f[e-1][i-1],f[e][k-i])}+1)),i\in[1,k] f[e][k]=min( max(f[e1][i1],f[e][ki])+1)),i[1,k]

代码记忆化搜索即可

代码:

#include
using namespace std;
const int inf=0x3f3f3f3f;
int f[1010][1010];
bool iscal[1010][1010];
void init(){
    memset(iscal,false,sizeof(false));
}
int F(int e,int k){
    if(k==0)
        return 0;
    if(e==0)
        return inf;//e=0 k>0 无解
    if(iscal[e][k])
        return f[e][k];
    int minn=inf;
    for(int i=1;i<=k;++i){
            minn=min(minn,max(F(e-1,i-1),F(e,k-i))+1);
    }
    iscal[e][k]=true;
    return f[e][k]=minn;
}
int main(){
    int e,k;
    init();
    while(~scanf("%d %d",&e,&k)){
        cout<<F(e,k)<<endl;
    }
    return 0;
}

你可能感兴趣的:(比赛技巧)