鸡蛋掉落问题 蛋碎如何理解_掉蛋问题

鸡蛋掉落问题 蛋碎如何理解

Problem statement:

问题陈述:

You are given N eggs, and building with K floors from 1 to K. Each egg is identical, you drop an egg and if an egg breaks, you cannot drop it again. You know that there exists a floor F with 0 <= F <= K such that any egg dropped at a floor higher than F will break, and any egg dropped at or below floor F will not break. Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X (with 1 <= X <= K). Your goal is to know with certainty what the value of F is.

您获得N个鸡蛋,并且建筑物的K层从1K。 每个鸡蛋都是相同的,您放下一个鸡蛋,如果鸡蛋破损,则不能再次放下。 您知道存在一个F 值为0 <= F <= K的地板F ,因此,落在高于F的地板上的任何鸡蛋都会破裂,而落在F或以下的鸡蛋不会破裂。 每一步,您都可以拿一个鸡蛋(如果您有一个完整的鸡蛋),然后将其从任意楼层X放下( 1 <= X <= K )。 您的目标是确定F的值。

What is the minimum number of moves that you need to know with certainty what F is, regardless of the initial value of F?

什么是你需要确切知道F是,不管F的初始值的移动的最低数量?

Input:

输入:

The first line of the input is T denoting the number of test cases. Then T test cases follow. Each test case contains one line denoting N number of eggs and K denoting K number of floors.

输入的第一行是T,表示测试用例的数量。 然后是T测试用例。 每个测试用例包含一行,表示N个蛋, K个表示K层蛋。

Output:

输出:

For each test case output in a new line the minimum number of attempts that you would take. F(F>=1 and F<=k).

对于换行中的每个测试用例输出,您将进行的最小尝试次数。 F(F> = 1且F <= k)。

Example with explanation:

带有说明的示例:

    Input: 
    T=1
    N=1 K=2

    Output: 
    2 
    Drop the egg from floor 1.  
    If it breaks, we know with certainty that F = 0.
    
    Otherwise, drop the egg from floor 2.  
    If it breaks, we know with certainty that F = 1.
    
    If it didn't break, then we know with certainty F = 2.
    Hence, 
    we needed 2 moves in the worst case to know what F is with certainty.

    Input: 
    T=1
    N=2,K=100

    Output: 
    14
    Minimum number of trials that we would need is 14 
    to find the threshold floor F.

Solution Approach

解决方法

1) Recursive Approach:

1)递归方法:

We have n eggs and k floors. The following are the possibilities,

我们有n个鸡蛋和k层地板。 以下是可能性,

When we drop an egg from a floor x, there can be two cases (1) The egg breaks (2) The egg doesn't break.

当我们从地板x上放一个鸡蛋时,可能有两种情况(1)鸡蛋破裂(2)鸡蛋没有破裂。

  1. If the egg breaks after dropping from xth floor, then we only need to check for floors lower than x with remaining eggs; so the problem reduces to x-1 floors and n-1 eggs.

    如果鸡蛋从x层掉落后破裂,那么我们只需要检查剩余鸡蛋的层数是否低于x层; 因此问题减少到x-1层和n-1个鸡蛋。

  2. If the egg doesn't break after dropping from the xth floor, then we only need to check for floors higher than x; so the problem reduces to k-x floors and n eggs.

    如果鸡蛋从第x层掉落后没有破裂,那么我们只需要检查高于x的层即可; 因此问题减少到kx层和n个鸡蛋。

Since we need to minimize the number of trials in the worst case, we take the maximum of two cases. We consider the max of the above two cases for every floor and choose the floor which yields the minimum number of trials.

由于我们需要在最坏的情况下尽量减少试验次数,因此我们最多采用两种情况。 我们考虑每个楼层的上述两种情况中的最大值,并选择产生最少试验次数的楼层。

Pseudo Code:

伪代码:

    k = Number of floors
    n = Number of Eggs

    Drop(n, k) = 	Minimum number of trials needed to find the 
				    threshold floor in worst case.
    Drop(n, k) = 	1 + min{max(Drop(n - 1, x - 1)
    Drop(n, k - x)) = x in {1, 2, ..., k}}

    int Drop(n,k):
    if(k==0||k==1)	//if floor is either 0 or 1 then
	    return k;	//simply return floor return k;

    if(n==1)    // if number of egg is one return number of floor
	    return k   

    if(n==0)	// if no egg is remaining then return 0
	    return 0;        

    int res=INT_MAX;  //initilise res with maximum value
    int subres;	 // for calculating recursive attemps value

    for(int i=1;i<=k;i++)
    {
	    // considering wordst case thats why calculating 
	    // the max attempt of the two.
	    subres=max(Drop(n-1,i-1),Drop(n,k-i));
	    res=min(res,1+subres)
    }    // 1 is added for the current attempt


    // then we pick the min of current attempts
    return res	         

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

ll Drop(ll n, ll k)
{
    if (k == 0 || k == 1) //base cases if floor is 0 or 1
        return k;
    if (n == 1) // if one egg simply return floor value
        return k;
    if (n == 0)
        return 0;
    ll res = INT_MAX;
    for (ll i = 1; i <= k; i++) {
        // max is taken because of worst case
        ll subres = max(Drop(n - 1, i - 1), Drop(n, k - i));
        // one is added because of current attempt
        res = min(res, 1 + subres);
    }
    return res; // return result.
}

int main()
{
    ll t;

    cout << "Enter number of test cases: ";
    cin >> t;

    while (t--) {
        cout << "Enter number of eggs and floors: ";
        ll n, k;
        cin >> n >> k;

        cout << "Minimum number of attempts: ";
        cout << Drop(n, k) << "\n";
    }
    return 0;
}

Output

输出量

Enter number of test cases: 3
Enter number of eggs and floors: 2 5
Minimum number of attempts: 3
Enter number of eggs and floors: 2 10
Minimum number of attempts: 4
Enter number of eggs and floors: 3 8
Minimum number of attempts: 4

The time complexity for the above approach is exponential hence it is valid only for a smaller number of inputs.

上述方法的时间复杂度是指数的,因此仅对较少数量的输入有效。

2) Dynamic Programming Approach

2)动态编程方法

Here will declare the state of our dynamic programming as dp[n][k] where n is the number of eggs we have and k is the floor we have at any instant of the moment.

这里将动态编程的状态声明为dp [n] [k] ,其中n是我们拥有的鸡蛋数, k是我们在任何时刻所拥有的地板。

There are base cases,

有基本情况,

dp[0][i]=0 if there is no egg then simply the answer is 0.
dp[1][i]=i if we have 1 egg then in the worst case we have to attempt all the floor to get the min number of attempts in the worst case.

dp [0] [i] = 0如果没有鸡蛋,则答案为0。
dp [1] [i] = i如果我们有1个鸡蛋,那么在最坏的情况下,我们必须尝试所有操作来获得最少的尝试次数。

We will see both of the approach top-down and bottom-up approach.

我们将看到自顶向下方法和自底向上方法。

Initially, we will fill all dp[n][k] with -1 for memorization approach.

最初,我们将用-1填充所有dp [n] [k]以便进行记忆。

So, that if it is calculated then return it immediately without calculating it again.

因此,如果已计算出该值,则立即将其返回,而无需再次计算。

2.1) Top Down Approach

2.1)自上而下的方法

pseudo code:

伪代码:

int Drop(n,k):
{	
	// base cases if floor is 0 or 1
	if(k==0||k==1)
		return k

	// if there is no eggs the reuturn 0
	if(n==0)
		return 0

	// if it iw calculate already then smiply return
	if(dp[n][k]!=-1)
		return dp[n][k] 

	// temporarly declare the max value of result
	int res=INT_MAX

	for(int i=1;i<=k;i++)
	{
		// find the max of the two cases
		int subres=max(Drop(n-1,i-1),Drop(n,k-i))  
		// 1 is added for current floor attempt
		res=min(res,1+subres)  
	}
	dp[n][k]=res;
	return dp[n][k]
}

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll dp[1004][1004];

ll Drop(ll n, ll k)
{
    if (k == 0 || k == 1) // base cases
        return k;
    if (n <= 0) //no eggs simply return 0
        return 0;
    if (dp[n][k] != -1) // memoized value return
        return dp[n][k];
    ll ans = INT_MAX;
    for (ll i = 1; i <= k; i++) {
        // maximum value for worst case condition
        ll subres = max(Drop(n - 1, i - 1), Drop(n, k - i));
        ans = min(ans, subres);
    }
    // one is added for current attempt
    dp[n][k] = 1 + ans;
    return dp[n][k];
}

int main()
{
    ll t;
    cout << "Enter number of test cases: ";
    cin >> t;

    while (t--) {
        cout << "Enter number of eggs and floors: ";
        ll n, k;
        cin >> n >> k;

        for (ll i = 0; i <= n; i++)
            for (ll j = 0; j <= k; j++)
                dp[i][j] = -1;

        dp[0][0] = 0;

        for (ll i = 1; i <= k; i++) {
            dp[0][i] = 0;
            dp[1][i] = i;
        }

        ll res = Drop(n, k);

        cout << "Minimum number of attempts: ";
        cout << res << "\n";
    }
    return 0;
}

Output

输出量

Enter number of test cases: 4
Enter number of eggs and floors: 2 10
Minimum number of attempts: 4
Enter number of eggs and floors: 2 100
Minimum number of attempts: 14
Enter number of eggs and floors: 2 36
Minimum number of attempts: 8
Enter number of eggs and floors: 2 1
Minimum number of attempts: 1

Time Complexity for the above approach in the worst case is O(nk^2).

在最坏的情况下,上述方法的时间复杂度为O(nk ^ 2)

Space Complexity for the above approach in the worst case is O(nk).

在最坏的情况下,上述方法的空间复杂度为O(nk)

2.2) Bottom Up Approach

2.2)自下而上的方法

Pseudo Code:

伪代码:

int Drop(int n, int k) 
{ 
	/* A 2D table where entery dp[i][j] will represent minimum 
	number of attempts needed for i eggs and j floors. */
	int dp[n+1][k+1]; 
	int res; 
	int i, j, x; 

	// We need one attempts for one floor and 0 attemts for 0 floors 
	for (i = 1; i <= n; i++) 
	{ 
		dp[i][1] = 1; 
		dp[i][0] = 0; 
	} 

	// We always need j attempts for one egg and j floors. 
	for (j = 1; j <= k; j++) 
		dp[1][j] = j; 

	// Fill rest of the entries in table using optimal substructure 
	// property 
	for (i = 2; i <= n; i++) 
	{ 
		for (j = 2; j <= k; j++) 
		{ 
			dp[i][j] = INT_MAX; 
			for (x = 1; x <= j; x++) 
			{ 
				// worst case condition
				res =max(dp[i-1][x-1], dp[i][j-x]); 
				if (res < dp[i][j]) 
				// plus one for current attempt 
				dp[i][j] = res+1;   
			} 
		} 
	} 

	// dp[n][k] holds the result 
	return dp[n][k]; 
} 

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int t;
    cout << "Enter number of test cases: ";
    cin >> t;

    while (t--) {
        int n, k;

        cout << "Enter number of eggs and number of floors: ";
        cin >> n >> k;

        int dp[n + 1][k + 1];
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 0; //if we have 0 eggs
        dp[0][1] = 0;

        for (int i = 1; i <= n; i++) {
            dp[i][0] = 0;
            dp[i][1] = 1;
        } // when we have 0 or 1 floor then we need 0 and one
        // attempts in worst case respectively

        for (int i = 1; i <= k; i++) {
            dp[0][i] = 0, dp[1][i] = i;
        } //base cases

        for (int i = 2; i <= n; i++) {
            for (int j = 2; j <= k; j++) {
                dp[i][j] = INT_MAX;
                for (int x = 1; x <= j; x++) {
                    // max for worst case
                    int subres = max(dp[i - 1][x - 1], dp[i][j - x]);
                    // one added for current attempts.
                    dp[i][j] = min(dp[i][j], 1 + subres);
                }
            }
        }

        cout << "Minimum number of attempts: ";
        cout << dp[n][k] << "\n";
    }

    return 0;
}

Output

输出量

Enter number of test cases: 3
Enter number of eggs and number of floors: 2 10
Minimum number of attempts: 4
Enter number of eggs and number of floors: 2 100
Minimum number of attempts: 14
Enter number of eggs and number of floors: 4 6
Minimum number of attempts: 2

Time Complexity for the above approach is O(n*k^2).

上述方法的时间复杂度为O(n * k ^ 2)

Space Complexity for the above approach is O(nk).

上述方法的空间复杂度为O(nk)

Problem reference: https://www.codechef.com/problems/CODEY202

问题参考: https//www.codechef.com/problems/CODEY202

翻译自: https://www.includehelp.com/icp/egg-dropping-problem.aspx

鸡蛋掉落问题 蛋碎如何理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值