项目排期 - 华为OD统一考试

OD统一考试(C卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

项目组共有N个开发人员,项目经理接到了M个独立的需求,每个需求的工作量不同,且每个需求只能由一个开发人员独立完成,不能多人合作。

假定各个需求直接无任何先后依赖关系,请设计算法帮助项目经理进行工作安排,使整个项目能用最少的时间交付。

输入描述

第一行输入为M个需求的工作量,单位为天,用逗号隔开。
例如:X1 X2 X3 … Xm
表示共有M个需求,每个需求的工作量分别为X1天,X2天…Xm天。其中0<M<30;0<Xm<200
第二行输入为项目组人员数量N
例如:
5
表示共有5名员工,其中0<N<10

输出描述

最快完成所有工作的天数
例如:
25
表示最短需要25天能完成所有工作

示例1

输入:
6 2 7 7 9 3 2 1 3 11 4
2输出:
28说明:
共有两位员工,其中一位分配需求6 2 7 7 3 2 1共需要28天完成,另一位分配需求9 3 11 4共需要27天完成,故完成所有工作至少需要28天。

题解

这道题可以使用二分查找 + 回溯来解决,二分的范围为需求工作量的最大值到总工作量的和。具体步骤如下:

  1. 定义一个二分查找范围,最小值为需求工作量的最大值 - 1,最大值为总工作量的和。
  2. 利用二分查找,查找最小的 MAX_SUM,使得每个人的工作量不超过 MAX_SUM。为了判断是否能满足条件,使用递归函数 ok (回溯法),在函数中模拟分配工作的过程,尝试将每个需求分配给不同的人员,看是否满足总工作量不超过 MAX_SUM。
  3. 如果能满足条件,则缩小二分查找范围为左半部分;否则,缩小二分查找范围为右半部分。
  4. 最终找到的二分查找范围左边界就是答案。

Java

import java.util.Arrays;
import java.util.Scanner;/*** @author code5bug*/
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取每个工作的工作量int[] works = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 读取开发人员的数量int N = scanner.nextInt();Solution solution = new Solution(works, N);System.out.println(solution.solve());}
}class Solution {int N;int[] works;public Solution(int[] works, int N) {this.N = N;this.works = works;}public int solve() {// 二分查找,找到最小的 MAX_SUM,使得每个人的工作量 <= MAX_SUMint l = Arrays.stream(works).max().getAsInt() - 1;int r = Arrays.stream(works).sum();while (l + 1 < r) {int mid = (l + r) >> 1;if (ok(0, mid, new int[N])) {r = mid;} else {l = mid;}}return r;}// 递归判断工作能否分配给 N 个人,使得每个人的总工作量 <= MAX_SUMprivate boolean ok(int idx, final int MAX_SUM, int[] sums) {if (idx == works.length) {return true;}for (int i = 0; i < N; i++) {// 尝试将 idx 个工作分配给第 i 个人员if (sums[i] + works[idx] <= MAX_SUM) {sums[i] += works[idx];if (ok(idx + 1, MAX_SUM, sums)) { // 可以完成分配,则直接返回 truereturn true;}sums[i] -= works[idx];}}return false;}
}

Python

from typing import Listworks = list(map(int, input().split()))
N = int(input())def ok(idx: int, MAX_SUM: int, sums: List[int]) -> bool:""":param idx: 索引下标:param MAX_SUM: 每人总工作量的限制(最大值):param sums:  sums[i] 表示第 i 个人需求的总工作量:return: 工作能否分配给 N 个人,使得每个人的总工作量 <= MAX_SUM"""global Nif idx == len(works):return Truefor i in range(N):if sums[i] + works[idx] <= MAX_SUM:  # 尝试将 idx 个工作分配给第 i 个人员sums[i] += works[idx]if ok(idx + 1, MAX_SUM, sums):return Truesums[i] -= works[idx]return False# 二分查找,找到最小的 MAX_SUM,使得每个人的工作量 <= MAX_SUM
# 每个需求只能由一个开发人员独立完成,因此 max(works) - 1 一定不可能是有效的解
l, r = max(works) - 1, sum(works)
while l + 1 < r:mid = (l + r) >> 1if ok(0, mid, [0] * N):r = midelse:l = mid
print(r)

C++

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cstring>using namespace std;int N, wlen = 0;
int sums[10 + 5];
int works[30 + 5];bool ok(int idx, const int MAX_SUM) {if (idx == wlen) {return true;}for (int i = 0; i < N; i++) {// 尝试将 idx 个工作分配给第 i 个人员if (sums[i] + works[idx] <= MAX_SUM) {sums[i] += works[idx];if (ok(idx + 1, MAX_SUM)) {return true;}sums[i] -= works[idx];}}return false;
}int main() {// 读取每个工作的工作量while(cin >> works[wlen++]) {if(cin.peek() == '\n') break;}// 读取开发人员的数量cin >> N;// 二分查找,找到最小的 MAX_SUM,使得每个人的工作量 <= MAX_SUMint l = *max_element(works, works + wlen) - 1;int r = accumulate(works, works + wlen, 0);while (l + 1 < r) {int mid = (l + r) >> 1;memset(sums, 0, sizeof(sums));if (ok(0, mid)) {r = mid;} else {l = mid;}}cout << r << endl;return 0;
}

‍❤️‍华为OD机试面试交流群每日真题分享): 加V时备注“华为od加群”

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/467482.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

响应式编程三流处理

响应式编程三流处理 组合响应式流concatmergezipcombineLatest flatMap、concatMap、flatMapSequebtial操作符flatMapconcatMapflatMapSequential 元素采样sample 和sampleTimeout 流的批处理bufferwindow操作符group by将响应式流转化为阻塞结构在序列处理时查看元素物化和非物…

day 20(补2.5)

fread 函数&#xff1a; 今日练习 C语言面试题5道~ 1. static 有什么用途&#xff1f;&#xff08;请至少说明两种&#xff09; 1) 限制变量的作用域 2) 设置变量的存储域 2. 引用与指针有什么区别&#xff1f; 1) 引用必须被初始化&#xff0c;指针不必。 2) 引用初始…

uniapp微信小程序开发踩坑日记:Pinia持久化

如果你使用过Pinia&#xff0c;那你应该知道Pinia持久化插件&#xff1a;https://prazdevs.github.io/pinia-plugin-persistedstate/zh/ 但由于官方文档提供的说明并不是针对小程序开发&#xff0c;所以我们在使用这个插件实现uniapp小程序开发中Pinia持久化会出现问题 我在C…

【深度学习】S2 数学基础 P1 线性代数(上)

目录 基本数学对象标量与变量向量矩阵张量降维求和非降维求和累计求和 点积与向量积点积矩阵-向量积矩阵-矩阵乘法 深度学习的三大数学基础 —— 线性代数、微积分、概率论&#xff1b; 自本篇博文以下几遍博文&#xff0c;将对这三大数学基础进行重点提炼。 本节博文将介绍线…

Illegal escape character in string literal

问题 笔者进行Android项目开发&#xff0c;编译器提示报错 Illegal escape character in string literal详细问题 textView.setText(“A\B”); 解决方案 修改代码为A\B textView.setText(“A\B”) 产生原因 问题产生的原因是在字符串字面值中使用了非法的转义字符。在…

猫头虎分享已解决Bug ‍ || 错误SyntaxError: invalid syntax(Python)的解决方法

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

编写代码(LLVM的第一个项目)

下面这个完整代码 它相对较短&#xff0c;因为它建立在LLVM 流程的基础设施上 后者替我们完成大部分工作 我们从程序使用cl命名空间中的llvm工具&#xff08;cl代表命令行&#xff09;来实现我们的命令行接口 需要调用ParseCommandLineOption函数声明cl&#xff1a;&#xff…

滑动小短剧影视微信小程序源码/带支付收益等模式

仿抖音滑动小短剧影视微信小程序源码&#xff0c;带支付收益等模式、支持无限滑动&#xff1b;高性能滑动、预加载、视频预览&#xff0c;支持剧情介绍&#xff0c;集合壁纸另外仿抖音滑动效果&#xff1b;支持会员模式&#xff0c;支持用户单独购买等等多功能。 丰富的后台设…

Vscode 在汇编文件中添加调试断点

Vscode 在汇编文件中添加调试断点 vscode默认不支持汇编文件添加断点, 可以在设置里面打开

开发自定义标记应用程序

开发自定义标记应用程序 问题陈述 Larry Williams 是ABC Inc.公司的CEO,他希望公司能够拥有一个交互式网站以向访问网站的用户表示问候并显示当前时间。他还希望最终用户能够指定主页的背景颜色。您是公司的网站管理员。Larry要您修改网站的主页,以便向最终用户显示自定义问…

19 删除链表的倒数第 N 个结点

19. 删除链表的倒数第 N 个结点 中等 相关标签 相关企业 提示 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 这段代码使用了双指针的方法&#xff0c;其中一个指针先走 n 步&#xff0c;然后两个指针一起走&#xff0c;直到第一…

Java强训day20(选择题编程题)

选择题 编程题 题目1 import java.util.Scanner;public class Main { public static void main(String[] args) {Scanner sc new Scanner(System.in);String s sc.nextLine();StringBuffer ss new StringBuffer(s);System.out.println(ss.reverse());sc.close();} }