贪吃的小Q--java实现

问题描述

小Q的父母要出差N天,走之前给小Q留下了M块奶糖。小Q决定每天吃的奶糖数量不少于前一天吃的一半,但是他又不想在父母回来之前的某一天没有奶糖吃,请问他第一天最多能吃多少块奶糖
输入描述: 
每个输入包含一个测试用例。 
每个测试用例的第一行包含两个正整数,表示父母出差的天数N(N<=50000)和巧克力的数量M(N<=M<=100000)。

输出描述: 
输出一个数表示小Q第一天最多能吃多少块奶糖。 
示例1 
输入 
3 7 
输出 
4

思想:二分的思想

上一下代码,具体的思路注释在代码里了,注意while层循环和for层循环的不同作用,while层循环主要是用来规划吃糖的计划的,for层循环来验证这样的计划是否可行,如果不行,那么再进while循环里二分规划下一个吃糖计划。

public class 贪吃的小Q {

    public static void main(String[] args) {
        int n,m,temp,now,mid;
        boolean flag;
        Scanner scanner = new Scanner(System.in);
        //父母的出差天数n
        n=scanner.nextInt();
        //一共有几块奶糖,奶糖数m
        m=scanner.nextInt();
        int l=1,r=m;
        while(l!=r)
        {   //如果够吃,那么flag就是true
            flag=true;
            //利用二分查找的思想来判断第一天最多能吃多少块
            mid=(l+r+1)/2;
            //temp保存的是奶糖总数m,在while这层循环里是不变的
            temp=m;
            //now可以理解为一次吃几个糖
            now=mid;
            //这个for循环很关键
            //注意条件j<n,n是父母出差的天数,这个for循环存在的意义就是看在父母回来之前怎么吃不会有一天吃不上
            //如果有一天吃不上了,也就意味着 当前剩余的奶糖数 < 按计划要吃的奶糖数了(temp<now)
            //这时就意味着第一天就吃多了,这个吃糖方案是不对的,需要break出for循环 重新规划 第一天吃多少糖
            //如果for能跑完,没有break,那么说明这样的吃糖方案是正确的,flag将会是true
            //mid保存的就还是成功方案的第一天吃的糖数,下面if语句中l=mid赋值后,输出l就是问题答案了。
            for(int j=0; j<n; j++)
            {
                //如果不够吃,跳出for循环,在while循环里从第一天吃多少开始重新规划方案。
                if(temp<now)
                {
                    flag=false;
                    break;
                }
                //此处的temp会根据前一天吃掉的奶糖数量更新
                // 比如一共有7块糖,第一天吃了4块,第二天就剩temp=temp-now=3块糖了
                temp-=now;
                //now就是按 每天吃的巧克力数量不少于前一天吃的一半 这样赋值的
                now=(now+1)/2;
            }
            if(flag)
                l=mid;
            else
                //这里的r就是重新规划第一天吃多少糖的体现,也是二分思想的体现
                //因为r被赋的初值是m,也就是奶糖的总数,这时r=mid-1意为着第一次吃的奶糖数 折半
                r=mid-1;
                //r被重新赋值后,判断一下是否l!=r,如果
        }
        System.out.println("小Q第一天最多能吃"+l+"个奶糖");

    }
}

大家可以debug一遍看一看,就好理解多了。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值