news 2026/8/13 10:22:39

华为OD机试新系统真题 【末世分配资源包】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
华为OD机试新系统真题 【末世分配资源包】

末世分配资源包(Java /C++/Py/Js/Go/C)题解

华为OD机试新系统真题 华为OD上机考试新系统真题 8月12号 200分题型

华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解

题目内容

末世时代,政府为各地分配资源,现有资源分配表nums[n],要求按如下规则分配给k kk个营地:

  1. 每个营地只分配一段连续的分配表
  2. 每个营地至少分到一份资源
  3. 所有的资源必须全部分出
  4. 分配方式:尽量平均分配(即:得利最大的营地获得的资源值尽量小)

输入描述

  1. 资源存储数组nums[n](资源数n nn:0 ≤ n ≤ 1000 0 \le n \le 10000n1000,每份资源数:1 ≤ n u m s [ i ] ≤ 100000 1 \le nums[i] \le 1000001nums[i]100000
  2. 营地数k kk1 ≤ k ≤ min ⁡ ( 50 , n ) 1 \le k \le \min(50, n)1kmin(50,n)

输出描述

在最优平均分配情况下,得利最大团队所获得的资源数

样例1

输入

4,3,6,9,7 2

输出

16

说明
可能的切分:

  • [4],[3,6,8,9,7],最大值:25
  • [4,3],[6,9,7],最大值:22
  • [4,3,6],[9,7],最大值:16
  • [4,3,6,9],[7],最大值:22
    因此,最大值最小的切分方式是第3种,返回16

样例2

输入

3,4,2,1 4

输出

4

说明
可能的切分:

  • [3],[4],[2],[1],最大值:4
    因此,最大值最小的切分方式是第1种,返回4

题解

思路:二分 + 贪心

  1. 这种在...条件下,求最值的基本都是是二分的套路题。见到这种题可以优先考虑二分算法进行处理。

  2. 首先确定上下边界

    • 下边界很容易想到为所有资源的最大值。
    • 上边界为所有资源总和,当k==1的会选择。
  3. 确定好上下边界时,每轮枚举上下边界中间值mid == (left + right) /2, 并判断在每组资源总数不超过mid下分配组数和k的关系,并按照大小关系更新上下边界,直到left == right时结束。更新上下边界规律如下

    • 分配组数 <= k,说明mid值刚好或者值太大,此时可以尝试更新值,更新right = mid
    • 分配组数 > k, 说明mid值太小,必须尝试更达至,更新left = mid + 1
  4. mid限制求解可分配组数采用贪心进行求解,使用sum记录当前组总和,cnt记录已分配组数量,从前往后遍历nums

    1. sum + nums[i] > mid说明该组无法继续容纳当前资源,需要重新分配一个组,更新cnt++, sum = nums[i]
    2. sum + nums[i] <= mid说明该组可以继续容纳当前资源,更新sum += nums[i]

C++

#include<bits/stdc++.h>#include<vector>usingnamespacestd;// 通用 切割函数 函数 将字符串str根据delimiter进行切割vector<int>split(conststring&str,conststring&delimiter){vector<int>result;size_t start=0;size_t end=str.find(delimiter);while(end!=string::npos){result.push_back(stoi(str.substr(start,end-start)));start=end+delimiter.length();end=str.find(delimiter,start);}// 添加最后一个部分result.push_back(stoi(str.substr(start)));returnresult;}intsolve(vector<int>&nums,intk){intn=nums.size();if(n==0){return0;}intleft,right;left=right=0;// 确定二分边界for(inti=0;i<n;i++){// 下边界为最大资源left=max(left,nums[i]);// 上边界为资源总和right+=nums[i];}while(left<right){intmid=(left+right)>>1;// 贪心计算分段数intcount=1;intsum=0;for(inti=0;i<n;i++){if(sum+nums[i]>mid){count++;sum=nums[i];}else{sum+=nums[i];}}// 值刚好或者值太大,尝试更小值if(count<=k){right=mid;// 值太小,应该升高}else{left=mid+1;}}returnleft;}intmain(){string input1;getline(cin,input1);intk;cin>>k;vector<int>nums=split(input1,",");cout<<solve(nums,k);return0;}

JAVA

importjava.io.*;importjava.util.*;publicclassMain{staticintsolve(int[]nums,intk){intn=nums.length;if(n==0){return0;}intleft=0;intright=0;// 确定二分边界for(inti=0;i<n;i++){// 下边界为最大资源left=Math.max(left,nums[i]);// 上边界为资源总和right+=nums[i];}while(left<right){intmid=(left+right)>>1;// 贪心计算分段数intcount=1;intsum=0;for(inti=0;i<n;i++){if(sum+nums[i]>mid){count++;sum=nums[i];}else{sum+=nums[i];}}// 值刚好或者值太大,尝试更小值if(count<=k){right=mid;// 值太小,应该升高}else{left=mid+1;}}returnleft;}publicstaticvoidmain(String[]args)throwsException{BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in));Stringinput1=br.readLine();intk=Integer.parseInt(br.readLine().trim());String[]parts=input1.split(",");int[]nums=newint[parts.length];for(inti=0;i<parts.length;i++){nums[i]=Integer.parseInt(parts[i].trim());}System.out.print(solve(nums,k));}}

Python

defsolve(nums,k):n=len(nums)ifn==0:return0left=0right=0# 确定二分边界foriinrange(n):# 下边界为最大资源left=max(left,nums[i])# 上边界为资源总和right+=nums[i]whileleft<right:mid=(left+right)>>1# 贪心计算分段数count=1sum_val=0foriinrange(n):ifsum_val+nums[i]>mid:count+=1sum_val=nums[i]else:sum_val+=nums[i]# 值刚好或者值太大,尝试更小值ifcount<=k:right=mid# 值太小,应该升高else:left=mid+1returnleft input1=input()k=int(input())nums=list(map(int,input1.split(",")))print(solve(nums,k),end="")

JavaScript

constreadline=require('readline');constrl=readline.createInterface({input:process.stdin,output:process.stdout});letinputs=[];rl.on('line',line=>{inputs.push(line);});rl.on('close',()=>{constinput1=inputs[0];constk=parseInt(inputs[1]);constnums=input1.split(',').map(Number);console.log(solve(nums,k));});functionsolve(nums,k){constn=nums.length;if(n===0){return0;}letleft=0;letright=0;// 确定二分边界for(leti=0;i<n;i++){// 下边界为最大资源left=Math.max(left,nums[i]);// 上边界为资源总和right+=nums[i];}while(left<right){constmid=Math.floor((left+right)/2);// 贪心计算分段数letcount=1;letsum=0;for(leti=0;i<n;i++){if(sum+nums[i]>mid){count++;sum=nums[i];}else{sum+=nums[i];}}// 值刚好或者值太大,尝试更小值if(count<=k){right=mid;// 值太小,应该升高}else{left=mid+1;}}returnleft;}

Go

packagemainimport("bufio""fmt""os""strconv""strings")funcsolve(nums[]int,kint)int{n:=len(nums)ifn==0{return0}left:=0right:=0// 确定二分边界fori:=0;i<n;i++{// 下边界为最大资源ifnums[i]>left{left=nums[i]}// 上边界为资源总和right+=nums[i]}forleft<right{mid:=(left+right)>>1// 贪心计算分段数count:=1sum:=0fori:=0;i<n;i++{ifsum+nums[i]>mid{count++sum=nums[i]}else{sum+=nums[i]}}// 值刚好或者值太大,尝试更小值ifcount<=k{right=mid// 值太小,应该升高}else{left=mid+1}}returnleft}funcmain(){in:=bufio.NewReader(os.Stdin)out:=bufio.NewWriter(os.Stdout)deferout.Flush()input1,_:=in.ReadString('\n')input2,_:=in.ReadString('\n')input1=strings.TrimSpace(input1)input2=strings.TrimSpace(input2)parts:=strings.Split(input1,",")nums:=make([]int,len(parts))fori,s:=rangeparts{nums[i],_=strconv.Atoi(strings.TrimSpace(s))}k,_:=strconv.Atoi(input2)fmt.Fprint(out,solve(nums,k))}

C语言

#include<stdio.h>#include<stdlib.h>#include<string.h>intsolve(int*nums,intn,intk){if(n==0){return0;}intleft=0;intright=0;// 确定二分边界for(inti=0;i<n;i++){// 下边界为最大资源if(nums[i]>left){left=nums[i];}// 上边界为资源总和right+=nums[i];}while(left<right){intmid=(left+right)>>1;// 贪心计算分段数intcount=1;intsum=0;for(inti=0;i<n;i++){if(sum+nums[i]>mid){count++;sum=nums[i];}else{sum+=nums[i];}}// 值刚好或者值太大,尝试更小值if(count<=k){right=mid;// 值太小,应该升高}else{left=mid+1;}}returnleft;}intmain(){charinput1[10000];charinput2[100];fgets(input1,sizeof(input1),stdin);fgets(input2,sizeof(input2),stdin);// 去除换行符input1[strcspn(input1,"\r\n")]='\0';input2[strcspn(input2,"\r\n")]='\0';int*nums=(int*)malloc(sizeof(int)*10000);intn=0;// 使用strtok按逗号切割char*token=strtok(input1,",");while(token!=NULL){nums[n++]=atoi(token);token=strtok(NULL,",");}intk=atoi(input2);printf("%d",solve(nums,n,k));free(nums);return0;}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/13 10:22:24

网站建设实用教程新手必读:从0到1打造高转化官网的避坑指南与落地策略

今天这篇内容,我想和大家掏心窝子聊聊“网站建设”这件事。为什么特意选在今天,是因为最近后台收到了太多朋友的私信和邮件,大多是被各种建站公司、模板平台搞得晕头转向,最后花了几万块钱做出来的网站,要么速度慢得像蜗牛,要么SEO效果为零,甚至连基本的移动端适配都做不…

作者头像 李华
网站建设 2026/8/13 10:19:14

如何在VSCode中实现秘密阅读?程序员必备的摸鱼插件完整指南

如何在VSCode中实现秘密阅读&#xff1f;程序员必备的摸鱼插件完整指南 【免费下载链接】Thief-Book-VSCode VScode 上一款真正的摸鱼插件 项目地址: https://gitcode.com/gh_mirrors/th/Thief-Book-VSCode 作为一名程序员&#xff0c;你是否曾想过在工作间隙偷偷看小说…

作者头像 李华
网站建设 2026/8/13 10:18:01

从零基础到独立建站完整揭秘:一份关于网页制作与网站建设项目教程的深度指南

在这个数字化浪潮汹涌澎湃的时代,拥有一个属于自己的网站,不再仅仅是互联网大厂的专利,也不再是那些穿着黑T恤、戴着厚底眼镜的极客们的专属特权。对于每一个普通人来说,掌握网页制作的技能,亲手搭建一个属于自己的网络空间,不仅是一种酷炫的生存技能,更是一种对自我表达…

作者头像 李华
网站建设 2026/8/13 10:16:26

从模糊需求到清晰实现:领域驱动设计与Spring Boot实践

在实际项目中&#xff0c;我们常常会遇到一些看似荒诞、非结构化的需求描述&#xff0c;例如“我在机场登机口等着一只穿着紫色小背心的鸭”。这类描述虽然不具备直接的技术含义&#xff0c;但它可以作为一个绝佳的引子&#xff0c;来探讨软件开发中一个核心且复杂的主题&#…

作者头像 李华