【二分法】编码能力提升

本文介绍了一个Java程序,通过二分法计算在给定天数限制下,完成一系列按难度排序的题目,使得在最多一天内花费的做题时间最小,同时满足每天只能做一道题且最多看一次答案的要求。
摘要由CSDN通过智能技术生成
import java.io.*;
import java.util.Arrays;

/**
 * 编码能力提升
 * 选中n道题,计划在m天刷完
 * 不能多天刷一题
 * 可以直接看答案,省去做题时间
 * 每天最多看一次答案
 * 定义m天中做题时间最多的一天耗时为T(直接看答案的题目不计入做题时间)
 * 求最小的T
 */
public class EncodingCapabilityEnhancementPlan {
    /**
     * times[i]的时间完成编号i的题目
     */
    private static int[] times;
    /**
     * 完成所有题目的天数限制
     */
    private static int daysLimit;
    /*
        999,998,997
        1
        -------------------
        1995
        +++++++++++++++++++
        999,998,997
        2
        -------------------
        997
        +++++++++++++++++++
        999,998,997
        3
        -------------------
        0
     */
    private static String line;
    private static String[] strArr;
    private static int length;

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        line = in.readLine();
        strArr = line.split(",");
        length = strArr.length;
        //将题目由易到难排序
        times = Arrays.stream(strArr).mapToInt(Integer::parseInt).sorted().toArray();
        //记录限制天数
        line = in.readLine();
        daysLimit = Integer.parseInt(line);
        //关闭接收器
        in.close();
        out.println(encodingCapabilityEnhancementPlan());
        out.flush();
        out.close();
    }

    /**
     * 二分法计算在限定天数内的最小T
     * @return              最小的T
     */
    public static int encodingCapabilityEnhancementPlan(){
        int result = -1;
        //做题时间最多的一天所花的最短时间(一天只做一道,且直接看答案)
        int low = 0;
        //做题时间最多的一天所花的最长时间(所有题一天做完,最难的一道看答案)
        int high = Arrays.stream(times).sum() - Arrays.stream(times).max().orElse(0);
        //二分法求在限定天数内的最小T
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (isFeasible(mid)) {
                result = mid;
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return result;
    }

    /**
     * 判断能否在规定时间内做完题
     * 不能多天完成同一题
     * 一天只能看一次答案
     * @param timeLimit     做题时间最多的一天所花的时间
     * @return              能否在规定时间内做完题
     */
    private static boolean isFeasible(int timeLimit) {
        //今天已经花了多少时间
        int currentDayTime = 0;
        //是否可以看答案
        boolean canSeeAnswer = true;
        //今天是做题第几天
        int currentDay = 1;
        //题号
        int i = 0;
        //循环刷题
        while (i < length) {
            //做完当前题,不超过时间限制
            if (currentDayTime + times[i] <= timeLimit) {
                //把这道题做完
                currentDayTime += times[i];
                //做下一题
                i++;
            } else {//已经没有时间做这道题
                if (canSeeAnswer) {//还可以看答案
                    //直接看答案
                    canSeeAnswer = false;
                    //做下一题
                    i++;
                } else {//不能看答案了
                    //时间切换到第二天
                    currentDay++;
                    //当天时间初始化
                    currentDayTime = 0;
                    //答案标记初始化
                    canSeeAnswer = true;
                }
            }
        }
        //所花费时间是否超过天数限制
        return currentDay <= daysLimit;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值