机考E卷100分题 - 爱吃蟠桃的孙悟空

题目描述

孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有 N 棵桃树,每颗树上都有桃子,守卫将在 H 小时后回来。

孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉 K 个,如果树上的桃子少于 K 个,则全部吃掉,并且这一小时剩余的时间里不再吃桃。

孙悟空喜欢慢慢吃,但又想在守卫回来前吃完桃子。

请返回孙悟空可以在 H 小时内吃掉所有桃子的最小速度 K(K为整数)。如果以任何速度都吃不完所有桃子,则返回0。

输入描述

一行输入为 N 个数字,N 表示桃树的数量,这 N 个数字表示每颗桃树上蟠桃的数量。

第二行输入为一个数字,表示守卫离开的时间 H。

其中数字通过空格分割,N、H为正整数,每颗树上都有蟠桃,且 0 < N < 10000,0 < H < 10000。

输出描述

吃掉所有蟠桃的最小速度 K,无解或输入异常时输出 0。

示例1

输入

2 3 4 5
4

输出

1

说明

示例2

输入

2 3 4 5
3

输出

0

说明

解题思路

本题22年、23年、24年都考过。

参考:875. 爱吃香蕉的珂珂 - 力扣(LeetCode)

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        // 创建一个Scanner对象用于读取输入
        Scanner cin = new Scanner(System.in);
        // 读取一行输入并转换为整数数组,代表每棵桃树上的桃子数量
        int[] peachCounts = Arrays.stream(cin.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        // 读取下一行输入,转换为整数,代表可用的小时数
        int h = Integer.parseInt(cin.nextLine());
        // 获取桃树的数量
        int n = peachCounts.length;
 
        // 输入验证:如果桃树数量为0,或小时数不合法,或桃树数量大于小时数,则输出0并返回
        if (n == 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
            System.out.println(0);
            return;
        }

        // 初始化二分查找的左右边界
        int left = 1, right = (int)1e9; // 假设最大的吃桃速度不会超过1e9
        // 当左边界小于右边界时,执行二分查找
        while (left < right) {
            // 计算中间值
            int mid = left + (right - left) / 2;
            // 如果以mid的速度可以在h小时内吃完桃子,则尝试更小的速度
            if (canFinish(peachCounts, h, mid)) {
                right = mid;
            } else {
                // 否则尝试更大的速度
                left = mid + 1;
            }
        }

        // 输出最小吃桃速度,此时left是满足条件的最小速度
        System.out.println(left);
    }

    // 定义一个方法,判断以速度k是否能在h小时内吃完所有桃子
    static boolean canFinish(int[] p, int h, int k) {
        // 初始化所需的总小时数
        int ans = 0;
        // 遍历每棵桃树
        for (int x : p) {
            // 计算吃完这棵桃树上桃子所需的小时数,向上取整
            ans += Math.ceil(x * 1.0 / k);
        }
        // 如果所需总小时数小于等于h,则返回true,表示可以完成
        return ans <= h;
    }
}

Python

import math

# 判断以速度k是否能在h小时内吃完所有桃子
def can_finish(p, h, k):
    ans = 0
    for x in p:
        ans += math.ceil(x / k)
    return ans <= h

# 读取输入
peach_counts = list(map(int, input().split()))
h = int(input())

# 输入验证
n = len(peach_counts)
if n == 0 or h <= 0 or n >= 10000 or h >= 10000 or n > h:
    print(0)
    exit(0)

# 二分查找最小吃桃速度
left, right = 1, int(1e9)
while left < right:
    mid = (left + right) // 2
    if can_finish(peach_counts, h, mid):
        right = mid
    else:
        left = mid + 1

# 输出最小吃桃速度
print(left)

JavaScript

// 读取标准输入
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 判断以速度k是否能在h小时内吃完所有桃子
function canFinish(p, h, k) {
    let ans = 0;
    for (let x of p) {
        ans += Math.ceil(x / k);
    }
    return ans <= h;
}

// 处理输入
rl.on('line', (input) => {
    if (!this.peachCounts) {
        // 第一行输入,转换为桃子数量数组
        this.peachCounts = input.split(' ').map(Number);
        return;
    }
    // 第二行输入,转换为小时数
    const h = Number(input);
    rl.close(); // 不再读取输入

    // 输入验证
    const n = this.peachCounts.length;
    if (n === 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
        console.log(0);
        return;
    }

    // 二分查找最小吃桃速度
    let left = 1, right = 1e9;
    while (left < right) {
        const mid = Math.floor((left + right) / 2);
        if (canFinish(this.peachCounts, h, mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    // 输出最小吃桃速度
    console.log(left);
});

C++

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <sstream>
using namespace std;

// 判断以速度k是否能在h小时内吃完所有桃子
bool canFinish(vector<int>& p, int h, int k) {
    long long ans = 0; // 使用 long long 防止溢出
    for (int x : p) {
        ans += ceil(x * 1.0 / k); // 向上取整
    }
    return ans <= h;
}

int main() {
    // 读取输入
    string line;
    getline(cin, line);
    istringstream iss(line);
    vector<int> peachCounts;
    int x;
    while (iss >> x) {
        peachCounts.push_back(x);
    }
    int h;
    cin >> h;

    // 输入验证
    int n = peachCounts.size();
    if (n == 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
        cout << 0 << endl;
        return 0;
    }

    // 二分查找最小吃桃速度
    int left = 1, right = 1e9; // 假设最大的吃桃速度不会超过1e9
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (canFinish(peachCounts, h, mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    // 输出最小吃桃速度
    cout << left << endl;
    return 0;
}

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

// 判断以速度k是否能在h小时内吃完所有桃子
int can_finish(int* p, int n, int h, int k) {
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += (int)ceil((double)p[i] / k);
    }
    return ans <= h;
}

int main() {
 
    char input[10000];
    fgets(input, sizeof(input), stdin);

    // 将输入分割并存入数组
    int peach_counts[10000];  
    int n = 0;

    char *token = strtok(input, " ");
    while (token != NULL) {
        peach_counts[n++] = atoi(token);
        token = strtok(NULL, " ");
    }


    int h;
    scanf("%d", &h);

    // 输入验证
    if (n == 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
        printf("0\n");
        return 0;
    }

    // 二分查找最小吃桃速度
    int left = 1, right = (int)1e9;
    while (left < right) {
        int mid = (left + right) / 2;
        if (can_finish(peach_counts, n, h, mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    // 输出最小吃桃速度
    printf("%d\n", left);

    return 0;
}
#华为##OD##牛客创作赏金赛#

主要记录自己的刷题日常,学而时习之。

全部评论
我放弃了,不会
点赞 回复 分享
发布于 11-13 17:54 广东

相关推荐

11-14 23:40
南昌大学 C++
1.513.找树左下角的值:树的最后一行的最左边的值。用层序遍历(队列)最好理解,只要记录最后一层的第一个元素即可。result设为全局变量,采用for循环控制条件只记录i=0时的值。2.112.&nbsp;路径总和:判断树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。递归法,遍历过程中直接对目标值进行更改,出口就是找到了叶子节点且目标值被减到0了,就true,否则false。里面其实涉及了回溯的过程,直接将每次遍历某个结点,目标值被修改后的值直接作为参数进行下一轮递归(由于每次递归调用都有它自己的&nbsp;targetSum&nbsp;副本(基于调用时的上下文),当递归返回时,上一层递归的&nbsp;targetSum&nbsp;仍然是它调用子递归之前的值(因为函数调用栈的帧被弹出,局部变量也随之销毁)),所以相当于是隐式地回溯了targetSum的值。值得注意的是,在257.&nbsp;二叉树的所有路径那道题中,参数是一个容器(如&nbsp;std::vector),情况就不同了。容器是按引用或指针传递的,或者更常见的是,我们直接传递容器的引用或指针以避免不必要的拷贝。在这种情况下,对容器的修改会影响到所有引用该容器的函数或对象。因此,在递归函数中处理容器时,我们需要显式地进行回溯,以确保在递归调用返回后,容器恢复到正确的状态。这通常是通过在递归调用之后从容器中移除添加的元素来实现的。总结来说,当我们按值传递基本数据类型(如&nbsp;int)时,递归调用自然地提供了回溯的效果,因为每个递归层都有自己的参数副本。但是,当我们传递容器或对象时,这些数据结构通常是在多个递归层之间共享的,因此我们需要显式地进行回溯来维护它们的状态。3.106.从中序与后序遍历序列构造二叉树:递归法对中序和后序数组进行切割,然后再去递归找到每一个子树的根节点左右节点。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//1.判断后序数组为空,则root为空结点&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//2.将后序数组最后一个元素设为根节点&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//3.根据根节点的值寻找中序数组中根节点的位置(for循环,得到位置下标就break),作为切割点&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//4.切割中序数组,得到左中序、右中序两段数组&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//5.切割后序数组,得到左后序、右后序两段数组&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//6.递归处理左子树(将切割出来的左中序、左后序作为参数)、右子树(将切割出来的右中序、右后序作为参数),返回的值分别为左右子树根节点的值。今天还学了一下如何用tinyXml2库解析RSS文件,下载了slickedit。晚上学院组织了个签约指导会,好想知道我们专业到底是什么神仙找到了工作啊啊啊。听老师们用民以食为天这句话忽悠了这么多年,今天还是头一回将这句话和让我们把思路打开联系上,说什么我们各行各业都能去,比如有驾照就可以去试试物流开车去。。。真是要疯了。一下子又被影响到心态了,怒投了几家。还投了之前实习过的中粮,但其实不想去,工资低的可怜。。还是要继续努力转码才行,本专业找工作的事就顺其自然吧,也不抱太大希望。
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务