丢鸡蛋问题(表示自己还是无法彻底理解)

题目:

  题目看的时候百度就好

我参考过的博客链接

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];
        
    }

}



点赞