华为OD- 工作安排-2024年OD(E卷)

题目描述

小明每周上班都会拿到自己的工作清单,工作清单内包含 n 项工作,每项工作都有对应的耗时时间(单位 h)和报酬,工作的总报酬为所有已完成工作的报酬之和,那么请你帮小明安排一下工作,保证小明在指定的工作时间内工作收入最大化。

输入描述

输入的第一行为两个正整数 T,n。 T 代表工作时长(单位 h, 0 < T < 1000000), n 代表工作数量( 1 < n ≤ 3000)。 接下来是 n 行,每行包含两个整数 t,w。 t 代表该工作消耗的时长(单位 h, t > 0),w 代表该项工作的报酬。

输出描述

输出小明指定工作时长内工作可获得的最大报酬。

用例
输入40 3 20 10 20 20 20 5
输出30
说明

解题思路

问题描述

我们有一段总时长为 total_time 的时间,以及若干任务,每个任务都有以下属性:

  • duration:完成任务所需的时间。
  • wage:完成任务获得的报酬。

目标是从这些任务中选择若干个,使得:

  • 总时间不超过 total_time
  • 收益(任务报酬的总和)最大化。

这是一个典型的 0-1 背包问题,将任务的时间视为物品的体积,任务的报酬视为物品的价值,总时间视为背包容量。

python源码:

class JobScheduler:
    def __init__(self, total_time, tasks):
        self.total_time = total_time  # 总时间
        self.tasks = tasks  # 任务列表,每个任务为 (时长, 报酬)

    def calculate_max_earnings(self):
        # 初始化 dp 数组
        dp = [0] * (self.total_time + 1)
        
        # 遍历每个任务
        for duration, wage in self.tasks:
            # 逆序更新 dp 数组,避免任务重复选择
            for time in range(self.total_time, duration - 1, -1):
                # 更新 dp[time],取不选择和选择当前任务的收益最大值
                dp[time] = max(dp[time], dp[time - duration] + wage)
        
        # 返回最大时间下的收益
        return dp[self.total_time]


if __name__ == "__main__":
    # 读取总时间和任务数量
    t, n = map(int, input().split())
    
    # 读取任务数据
    tasks = [tuple(map(int, input().split())) for _ in range(n)]
    
    # 创建任务调度器并计算结果
    scheduler = JobScheduler(t, tasks)
    print(scheduler.calculate_max_earnings())

java源码:

import java.util.Scanner;

class Main {
    private int totalTime; // 总时间限制
    private int[][] tasks; // 任务数组,每个任务包含两个值:[时长, 报酬]

    // 构造函数,初始化总时间和任务数组
    public Main(int totalTime, int[][] tasks) {
        this.totalTime = totalTime;
        this.tasks = tasks;
    }

    // 动态规划计算最大收益
    public int calculateMaxEarnings() {
        int[] dp = new int[totalTime + 1]; // dp数组,dp[time]表示总时间为time时的最大收益

        // 遍历每个任务
        for (int[] task : tasks) {
            int duration = task[0]; // 任务时长
            int wage = task[1];     // 任务报酬

            // 从后向前遍历时间,避免任务重复选择
            for (int time = totalTime; time >= duration; time--) {
                // 选择或不选择当前任务,取最大收益
                dp[time] = Math.max(dp[time], dp[time - duration] + wage);
            }
        }

        // 返回最大时间下的最大收益
        return dp[totalTime];
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 读取总时间和任务数量
        int totalTime = sc.nextInt();
        int numTasks = sc.nextInt();
        int[][] tasks = new int[numTasks][2]; // 任务数组

        // 读取每个任务的时长和报酬
        for (int i = 0; i < numTasks; i++) {
            tasks[i][0] = sc.nextInt(); // 时长
            tasks[i][1] = sc.nextInt(); // 报酬
        }

        // 创建任务调度器并计算结果
        Main scheduler = new Main(totalTime, tasks);
        System.out.println(scheduler.calculateMaxEarnings());
    }
}

js源码:

待更新......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛快快快快跑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值