双蛋问题

4 篇文章 0 订阅

前几天看了李永乐老师的视频、忽然想写一下博客:

1,问题描述:

有i层楼,2个鸡蛋,鸡蛋是相同的,临界楼层是指从某个楼层之上抛下来,都会碎,但从这个楼层之下抛下来,都不会碎。没有碎的鸡蛋可以重复使用。试假设能找到这个临界楼层需要抛投的最少次数。

2、问题分析

2.1假设1:

假设楼层i为100
第一个鸡蛋直接从楼层的一半扔下去:
假设第一个鸡蛋没碎:
第二个鸡蛋最坏的情况为1+(i/2-1-1)
假设第一个鸡蛋碎了
第二个鸡蛋最坏的情况还是1+(i/2-1-1)
最坏的情况下是49次

2.2假设2:使用开平方法

假设100层楼
第一个鸡蛋从10层楼扔下去
最坏的情况为 (i/10-1)+10-1 = 19次

2.3假设3:使用高斯公式(2个鸡蛋使用这个次数最少)

文字表述:和=(首项 + 末项)x项数/2
数学表达:1+2+3+4+……+ n = (n+1)n /2

//使用循环求出次数
private static int layer;   //楼层数量
    private static int egg;    //鸡蛋数量
    private static int minNum; //最优解法:在layer层楼、egg个鸡蛋的时候,一定能找到临界楼层的最初抛投次数
    private static int maxInterval; //间隔的值之和:1、2、3、4的和小于楼层数量
    public static void main(String[] args) {
        layer = 200;  //楼层数量赋值
        egg = 2;    //鸡蛋数量赋值
//        getMin();
    }
    private static int getMin(){
        int num = 1;    //声明初始化间距为1
        minNum = recursionMin(num,layer);
        System.out.println(minNum);
        return minNum;
    }
    private static int  recursionMin(int num,int layer){
        if (maxInterval < layer && maxInterval + 1 != layer) {
            //num每次从一开始加    maxInterval为最大值:如果楼层为100最大值为1、2、3、4。。。14的和
            num = num + 1;
            maxInterval += num;
            return recursionMin(num,layer);
        } else {
            return num;
        }
    }
//解高斯方程求出次数
public static void main(String[] args) {
        layer = 100;  //楼层数量赋值
        egg = 2;    //鸡蛋数量赋值
        getEquation(layer);
    }
    public static int getEquation(int layer){
        double n;
        //补了一下小学数学--!套入公式(n+1)*n/2 = layer然后解方程
        /*
        * (x-a)(x-a) = 0
        * x*x -ax -ax + a*a = 0
        * x*x - 2ax + a*a = 0
        * 解方程步骤:
        *   (n+1)*n = layer * 2
        *   n*n + n = layer *2
        *   n*n + 2*1/2*n + 1/2 * 1/2 = layer *2 + 1/2*1/2
        *   (n+1/2)*(n+1/2) = layer *2 + 1/4
        *   (n+1/2)*(n+1/2) = (layer * 2 * 4 + 1)/4
        *   n + 1/2 = Math.sqrt((layer * 2 * 4 + 1)/4)
        *   n = Math.sqrt((layer * 2 * 4 + 1)/4))  - 1/2
        * */
        int gen = layer*2+1/4;
        //1/2只会按整型运算,结果也是整形的所以==0 必须使用1.0/2.0
        n = Math.ceil(Math.sqrt(gen) - 1.0/2.0);
        return 1;
    }

2.4多蛋情况下使用递归找出所有运算结果中次数最少的(运算的很慢很慢)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class DuoDan {
    private static int layer;   //楼层数量
    private static int egg;    //鸡蛋数量
    private static int minNum; //最优解法:在layer层楼、egg个鸡蛋的时候,一定能找到临界楼层的最初抛投次数

    public static void main(String[] args) {
        layer = 30;  //楼层数量赋值
        egg = 3;    //鸡蛋数量赋值
        getMin();
    }
    private static int getMin() {
        recursionEgg(layer,egg);
        System.out.println(minNum);
        return minNum;
    }
    private static int recursionEgg(int layer,int egg){
        if(layer <= 0){
            //楼层数量小于0返回0
            return 0;
        }
        if(layer <= 1){
            //楼层数量小于1返回1
            return layer;
        }
        if(egg <= 1){
            //鸡蛋个数小于1返回剩余楼层数量
            return layer;
        }
        List<Integer> num = new ArrayList<Integer>();
//        int i = 5;
        //第一次求第一次重第几层往下扔
        for (int i = 1;i<layer;i++){
            //求出从1-n层楼往下扔鸡蛋的每次需要的最多次数
            num.add(recursionMax(layer,egg,i));
        }
        minNum = Collections.min(num);
        //取出一个最小值
        return minNum;
    }
    private static int  recursionMax(int layer,int egg,int k) {
        //k是当前从第几层楼开始扔
        if(k <= 0){
            //如果在第一层的话鸡蛋碎了会变成0  默认赋值1
            k = 1;
        }
        if(layer <= 0){
            //楼层数量小于0返回0
            return 0;
        }
        if(layer <= 1){
            //楼层数量小于1返回1
            return layer;
        }
        if(egg <= 1){
            //鸡蛋个数小于1返回剩余楼层数量
            return layer;
        }
        if (egg > 2) {
            //判断如果鸡蛋数量大于2的情况下循环递归调用
 //        没碎                                                    碎了
            return Math.max(recursionEgg(layer-k,egg),recursionEgg(k-1,egg-1))+1;
        }
//        //没碎                                                    碎了
//        //每扔一次数就加1、的出最坏情况下需要扔几次
        return Math.max(recursionMax(layer - k,egg,k-1),recursionMax(k-1,egg-1,k-1))+1;
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值