您的位置:首页 > 运维架构

DP11 高楼扔鸡蛋问题 Egg Dropping Puzzle @geeksforgeeks

2013-12-26 02:18 525 查看
package DP;

/**
* 100层楼,两个鸡蛋。某层之上扔鸡蛋就会碎。问至少要测试多少次才能找出这层楼来
* 我们可以决定怎么扔(min),但必须假设我们的运气最差(max)
*
* 100层楼,两个鸡蛋。某层之上扔鸡蛋就会碎。问至少要测试多少次才能找出这层楼来?

思路:
首先要理解清楚题意,本题不是要找在哪一层以上会把鸡蛋扔破!而是我们假设在W层以上会把鸡蛋仍破,现在问至少要测试Y次才能找到这个W层?求的是Y
另外一个要注意的是本题中要基于扔的人运气最差的情况,即要保证在worst case下也能找到。
定义W层位蛋破层,则
我们第一次从第x层扔蛋下去,有两种可能:
1) 蛋破了:这说明了两点  1.我们手上仍然有n-1颗蛋  2.蛋破层一定在1...x-1之间,这里共有x-1-1+1 =>x-1数量的嫌疑楼层
2)蛋没破:这也说明了两点  1.我们手上仍然有n颗蛋  2.蛋破层一定在x+1...k之间,这里共有k-(x+1)+1 =>k-x数量的嫌疑楼层

定义eggDrop(n, k)为在最差情况下找出蛋破层所需要的最少扔数。n为蛋的数量,k为要检查的连续的楼层的数量
因为我们要基于最差情况,所以我们要选择两种可能之间更坏的那种,即导致扔的数量更多的那种情况,
即max(eggDrop(n - 1, x - 1), eggDrop(n, k - x))
然后我们遍历所有楼层,要找出能使得最后扔的数量最小的那个初始楼层,因此
eggDrop(n, k) = 1 + min{max(eggDrop(n - 1, x - 1), eggDrop(n, k - x)): x in {1, 2, ..., k}}
加1是因为在第x层测试时也消耗了1次。
*/
public class EggDroppingPuzzle {

public static void main(String[] args) {
int n = 2, k = 20;
System.out.println(eggDropDP(n, k));
System.out.println(eggDropRec(n, k));
}

/* Function to get minimum number of trails needed in worst
case with n eggs and k floors */
// n: 手上完好蛋的数量
// k: 要测试的连续楼层的数量
public static int eggDropRec(int n, int k){
// If there are no floors, then no trials needed. OR if there is
// one floor, one trial needed.
if(k==1 || k==0){
return k;
}
// We need k trials for one egg and k floors
if(n == 1){
return k;
}
int min = Integer.MAX_VALUE;

/**
我们要决策怎么扔使得总扔数最少(即使在我们运气最差的情况下)worst-case
所以在每一楼都测试第一扔,然后递归计算出总共需要的扔数,找到扔数最小的数量
所以假设在第x层扔第一个蛋:
结果1:蛋破了->现在我们只有n-1个蛋,还要测试x-1数量的楼层[1,x-1] -> 数量=x-1 -1 + 1 = x-1
结果2: 但没破 -> 现在我们仍有n个蛋,还要测试k-x数量的楼层[x+1,k] -> 数量=k - (x+1) + 1 = k-x
*/
for(int x=1; x<=k; x++){
int res = Math.max(eggDropRec(n-1, x-1), eggDropRec(n, k-x));
min = Math.min(min, res);
}
return min+1;		// +1是因为测试当前层消耗了一次扔
}

/* Function to get minimum number of trails needed in worst
case with n eggs and k floors */
// Time Complexity: O(nk^2), Auxiliary Space: O(nk)
public static int eggDropDP(int n, int k){
/* A 2D table where entery dp[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int[][] dp = new int[n+1][k+1];

// We need one trial for one floor and0 trials for 0 floors
for(int i=1; i<=n; i++){
dp[i][1] = 1;
dp[i][0] = 0;
}
// We always need j trials for one egg and j floors.
for(int j=1; j<=k; j++){
dp[1][j] = j;
}
// Fill rest of the entries in table using optimal substructure
// property
for(int i=2; i<=n; i++){			// i eggs
for(int j=2; j<=k; j++){	// j floors
dp[i][j] = Integer.MAX_VALUE;
for(int x=1; x<=j; x++){	// try every floor from 1...j
int res = 1 + Math.max(dp[i-1][x-1], dp[i][j-x]);
dp[i][j] = Math.min(dp[i][j], res);
}
}
}
return dp
[k];
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: