机器人板砖【华为OD面试题目】

题目:

机器人搬砖,一共有 N 堆砖存放在 N 个不同的仓库中,第 i 堆砖中有 bricks[i] 块砖头,要求在 8 小时内搬完。

机器人每小时能搬砖的数量取决于有多少能量格,机器人一个小时中只能在一个仓库中搬砖,机器人的能量格只在这一个小时有效,为使得机器人损耗最小化,应尽量减小每次补充的能量格数。

为了保障在 8 小时内能完成搬砖任务,请计算每小时给机器人充能的最小能量格数。

  • 无需考虑机器人补充能力格的耗时;

  • 无需考虑机器人搬砖的耗时;

  • 机器人每小时补充能量格只在这一个小时中有效;

输入描述

第一行为一行数字,空格分隔

输出描述

机器人每小时最少需要充的能量格,若无法完成任务,输出 -1

import java.util.Arrays;
import java.util.Scanner;

public class Test15 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] bricks = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        System.out.println(getResult(bricks));
    }

    public static int getResult(int[] bricks) {
        // 机器人每小时只能在一个仓库干活,因此给定8小时,最多只能搬完8个仓库,如果仓库数量超过8,那么肯定干不完
        if (bricks.length > 8) {
            return -1;
        }

        // 每小时最多需要的能量块
        int max = Arrays.stream(bricks).max().orElse(0);

        // 如果有8个仓库,那么只能1个小时干1个仓库,且机器人每小时需要能量至少是max(bricks),这样才能保证1个小时内把最多砖块的那个仓库搬完
        if (bricks.length == 8) {
            return max;
        }

        // 如果仓库数少于8个,那么此时每小时能量max(bricks)必然能在8小时内搬完所有仓库,但不是最优解
        int ans = max;

        // 每小时最少需要的能量块
        int min = 1;

        // 二分法
        while (min <= max) {
            // 取中间值
            int mid = (min + max) >> 1;

            if (check(mid, 8, bricks)) {
                // 如果每小时充mid格能量,就能在8小时内,搬完所有砖头,则mid就是一个可能解
                ans = mid;
                // 但mid不一定是最优解,因此继续尝试更小的能量块
                max = mid - 1;
            } else {
                // 如果每小时充mid能量块,无法在8小时能完成工作,则说明每天能量块充少了,下次应该尝试充更多能量块
                min = mid + 1;
            }
        }

        return ans;
    }

    /**
     * @param energy 每小时可以使用的能量块数量
     * @param limit  限制几小时内干完
     * @param bricks 要搬几堆砖头
     * @return 是否可以在limit小时内已指定energy能量办完所有bricks
     */
    public static boolean check(int energy, int limit, int[] bricks) {
        // 已花费的小时数
        int cost = 0;

        for (int brick : bricks) {
            cost += brick / energy + (brick % energy > 0 ? 1 : 0);

            // 如果搬砖过程中发现,花费时间已经超过限制,则直接返回false
            if (cost > limit) {
                return false;
            }
        }

        return true;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值