The following is a description of the instance of this famous puzzle involving n=2 eggs and a building with k=36 floors.
Suppose that we wish to know which stories in a 36-story building are safe to drop eggs from, and which will cause the eggs to break on landing. We make a few assumptions:
…..An egg that survives a fall can be used again.
…..A broken egg must be discarded.
…..The effect of a fall is the same for all eggs.
…..If an egg breaks when dropped, then it would break if dropped from a higher floor.
…..If an egg survives a fall then it would survive a shorter fall.
…..It is not ruled out that the first-floor windows break eggs, nor is it ruled out that the 36th-floor do not cause an egg to break.
If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases?
The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized.
题目的大意是 有一个36层的建筑,用2个鸡蛋来确定从哪一层扔下鸡蛋而鸡蛋不会破碎,可以摔碎两个鸡蛋,求最少的测试次数是多少?
问题的关键之处在于找到一种测试方案,在这种测试方案中,无论鸡蛋会在哪一层被摔碎,都至多需要m次测试,在所有这些测试方案中,m的值最小。
解决的一种思路是把这个问题一般化,假设有n个鸡蛋k层楼,记为E(n,k),试着从每一层掉落一个鸡蛋(从1到k)并递归计算需要在最坏的情况下需要的最小测试次数。
最优子结构
当我们从一个楼层x扔下鸡蛋时,有可能出现两种情况(1)鸡蛋破 (2)鸡蛋不破
1)从x层扔下鸡蛋,如果鸡蛋破了,则需要用剩下的鸡蛋检测x层以下的楼层;问题简化为x-1层和n-1个鸡蛋。
2)从x层扔下鸡蛋,如果鸡蛋没有破,只需要检测比x高的层楼;问题简化为k-x层 和 n个鸡蛋。
鉴于我们需要把最坏情况下的测试次数最小化,我们取这两种情况的最大值。假设这两种情况下尝试的次数分别是p、q,取两个次数的最大值(假设p是最大的),与第1次在x层执行测试的这1次相加,则p+1就是第一次将鸡蛋扔在x层来解决E(n,k)所需要的最小测试次数。
k:层楼的层数
n:鸡蛋的数量
eggDrop(n,k):最坏情况下需要的最小尝试次数(考虑了所有的情况)
eggDrop(n,k) = 1+min{ max(eggDrop(n-1,x-1),eggDrop(n,k-x))} ,其中x的范围是{1,2,3,...,k} 。
public class EggDrop {
public static void main(String args[]) {
int n = 2, k = 36;
System.out.println(n + "个鸡蛋和 " + k + "层楼在最坏情况下尝试的最小次数是" + eggDrop(n, k));
}
/**
*
* @param n:鸡蛋数
* @param k:楼层数
* @return eggFloor[n][k]:n个鸡蛋k层楼的最小尝试次数
*/
public static int eggDrop(int n, int k) {
int eggFloor[][] = new int[n + 1][k + 1];
int res = 0;
int i, j, x;
// 楼层数是1,需要尝试1次;楼层数是0时,尝试0次。
for (i = 1; i <= n; i++) {
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
// 1个鸡蛋j层楼的尝试次数为j,没法优化。
for (j = 1; j <= k; j++) {
eggFloor[1][j] = j;
}
// 最优子结构的递推
for (i = 2; i <= n; i++) {
for (j = 2; j <= k; j++) {
eggFloor[i][j] = Integer.MAX_VALUE;
for (x = 1; x <= j; x++) {
res = 1 + Math.max(eggFloor[i - 1][x - 1], eggFloor[i][j- x]);
if (res < eggFloor[i][j]) {
eggFloor[i][j] = res;
}
}
}
}
return eggFloor[n][k];
}
}
本篇博客参考了:http://www.geeksforgeeks.org/dynamic-programming-set-11-egg-dropping-puzzle/