题目:
题目看的时候百度就好
我参考过的博客链接
http://spencermortensen.com/articles/egg-problem/
https://blog.csdn.net/Autumn03/article/details/80886814
第二个链接里面讲了好几种解题方法,并且动态规划也讲得比较细致。
第一个链接,我感觉那个方法是把动态规划转换成了数学公式,对于计算机来说,用处不大,并且在鸡蛋数增加之后,公式得推导有点可怕,数学好的同学可以试试。
个人的实现代码:
我自己的这部分并没有写推导过程,过程可参考第二个链接,我在代码的注释里面解释得足够理解这个转移方程(个人感觉)。
package ray.oj.test;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
System.out.println(dropEggs(input.nextInt(), input.nextInt()));
}
}
private static int dropEggs(int eggs, int floors) {
if(eggs==0 || floors==0) {//没有egg 或 floor, 没有意义, 直接返回.
return 0;
}
int[][] dp = new int[eggs+1][floors+1];//状态转移数组
//初始化状态转移数组
for(int i=0; i<=eggs; i++) {
for(int j=0; j<=floors; j++) {
if(i==0 || j==0) {//楼层为0, 理所应当为0
dp[i][j] = 0;
} else if (j==1) {//只有一层楼, 所以最后结果肯定为1
dp[i][j] = 1;
} else { //每一层楼对应的最大的次数都是楼层数本身
dp[i][j] = j;
}
}
}
for(int egg=2; egg<=eggs; egg++) {
for(int floor=2; floor<=floors; floor++) {
//drop表示每一次最开始丢的楼层数
for(int drop=1; drop<=floor; drop++) {
//这是个状态转移方程
/**
* dp[egg-1][drop-1]+1, 表示在egg个鸡蛋, drop层时, 鸡蛋碎了, 因此将问题变成( egg-1 )个鸡蛋, drop-1层的答案 加1
* dp[egg][floor-drop]+1 表示在egg个鸡蛋, drop层时, 鸡蛋没碎, 因此问题转换成( egg )个鸡蛋, floor-drop的答案 加1
* 在每一次的判断之后, 问题转成两个子问题, 结果取两个子问题的max值,
*
* 子问题的构成:
* 一个新的丢鸡蛋问题,
* 鸡蛋数: 碎:egg-1, 没碎:egg
* 楼层数: 碎:drop-1, 没碎:floor-drop;
*
* 最终子问题转换成: 鸡蛋数为1, 楼层不定, 的一个子问题
*
*/
/**
* 一共有floor种丢法, 每一种丢法的时候, 结果取max值
* 但是在floor种丢法之间比较时选择最小值, 这样才能保证答案是最小的
* 整个过程是从 1个鸡蛋, 1层楼 的子问题开始, 逐渐向高的层数和鸡数迭代, 即由下向上迭代
* 当迭代完成后, dp[i][j] 即表示 i个鸡蛋, j层楼, 的丢鸡蛋问题的解, 所以迭代完之后, dp数组是一个丢鸡蛋问题的解集
*/
dp[egg][floor] = Math.min(dp[egg][floor], Math.max(dp[egg-1][drop-1]+1, dp[egg][floor-drop]+1));
}
}
}
return dp[eggs][floors];
}
}