E卷-最大报酬(100分)

最大报酬

问题描述

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

输入格式

第一行包含两个正整数 代表工作时长(单位 h), 代表工作数量。 接下来 行,每行包含两个整数 代表第 项工作消耗的时长(单位 h), 代表第 项工作的报酬。

输出格式

输出一个整数,表示小明在指定工作时长内可获得的最大报酬。

样例输入

40 3
20 10
20 20
20 5

样例输出

30

样例解释

数据范围

  • 为整数

题解

这道题目本质上是一个 0-1 背包问题。每项工作可以看作是一个物品,工作时长就是物品的重量,报酬就是物品的价值。我们需要在有限的时间(背包容量)内,选择一些工作(物品)来获得最大的报酬(价值)。

解决这个问题的关键在于使用动态规划。定义一个二维数组 dp[i][j],表示前 i 个工作在 j 小时内能获得的最大报酬。状态转移方程如下:

dp[i][j] = max(dp[i-1][j], dp[i-1][j-t[i]] + w[i])  if j >= t[i]
dp[i][j] = dp[i-1][j]                               if j < t[i]

这个方程的含义是:对于第 i 个工作,有两种选择:做或不做。如果不做,那么最大报酬就是前 i-1 个工作在 j 小时内的最大报酬。如果做,那么需要先腾出这个工作所需的时间,然后加上这个工作的报酬。

算法的主要步骤如下:

  1. 初始化 dp 数组,所有元素设为 0。
  2. 遍历每个工作。
  3. 对于每个工作,遍历从该工作所需时间到总时间 T 的每个时间点。
  4. 对于每个时间点,计算做这个工作和不做这个工作两种情况下的最大报酬,取较大值。
  5. 最终答案就是

在实际实现中,可以使用滚动数组来优化空间复杂度到 O(T)。这种优化不会改变时间复杂度,但可以大大减少内存使用。

参考代码

  • Python
# 读取输入
T, n = map(int, input().split())
jobs = [list(map(int, input().split())) for _ in range(n)]

# 初始化dp数组
dp = [0] * (T + 1)

# 动态规划过程
for t, w in jobs:
    for j in range(T, t - 1, -1):
        # 状态转移:选择当前工作或不选择
        dp[j] = max(dp[j], dp[j - t] + w)

# 输出结果
print(dp[T])
  • C
#include <stdio.h>
#include <string.h>

#define MAX_T 1000000
#define MAX_N 3000

int main() {
    int T, n;
    int t[MAX_N], w[MAX_N];
    int dp[MAX_T + 1];

    // 读取输入
    scanf("%d %d", &T, &n);
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &t[i], &w[i]);
    }

    // 初始化dp数组
    memset(dp, 0, sizeof(dp));

    // 动态规划过程
    for (int i = 0; i < n; i++) {
        for (int j = T;

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

算法刷题笔记 文章被收录于专栏

本专栏收集并整理了一些刷题笔记

全部评论
有需要的宝子可以订阅专栏哦~
点赞 回复 分享
发布于 10-23 16:51 浙江
用贪心来解决可不可以,float定义一个赚钱效率,按这个效率排序,先干赚钱效率高的工作。
点赞 回复 分享
发布于 10-25 13:11 山东

相关推荐

点赞 评论 收藏
分享
1 3 评论
分享
牛客网
牛客企业服务