蓝桥杯 第2945题 课程抢购 C++ Java Python

32 篇文章 5 订阅
5 篇文章 0 订阅

目录

题目

思路和解题方法

c++ 代码

Java 版本(仅供参考)

Python 版本(仅供参考)

代码细节:

C++ 代码细节解释:

Python 代码细节解释:


lenyan算法笔记 · 语雀 《lenyan算法笔记》

个人笔记日常更新。含金量不高。/(ㄒoㄒ)/~~

题目

思路和解题方法

  1. 首先,定义了一个结构体 Course 来表示每门课程的截止时间、等待时间和含金量。
  2. main 函数中,首先读入课程数量 n,然后读入每门课程的信息,并将它们按照截止时间升序排序。
  3. 接下来,定义了一个二维数组 dp,其中 dp[i][j] 表示在前 i 门课程中,截止时间为 j 时能够获得的最大含金量。
  4. 初始化 dp 数组,将所有元素置为 0。
  5. 接着,进行动态规划的状态转移。对于每一门课程 i,遍历所有可能的截止时间 j,更新 dp[i][j]
    • 如果当前时间 j 大于等于课程 i 的截止时间,并且从当前时间往前推等待时间仍然在有效范围内,则尝试将课程 i 加入购买考虑,并更新 dp[i][j]
    • 在更新 dp[i][j] 时,可以选择将课程 i 加入购买考虑或不加入,取两者中含金量更高的那个。
  6. 最终,输出 dp[n][a[n].jie],表示在考虑了所有课程后,在截止时间为最后一门课程的截止时间时能够获得的最大含金量。

c++ 代码

#include<bits/stdc++.h> // 包含了常用的数据结构和算法函数的头文件
using namespace std;
using ll = long long; // 定义long long类型的别名,方便表示大整数

// 定义一个结构体lesson,表示每个任务的属性
struct lesson{
    ll wait, dead, value; // wait: 任务的等待时间, dead: 任务的截止时间, value: 完成任务获得的价值
}a[55]; // 定义一个lesson类型的数组,最多存储55个任务

const int N = 1e5 + 7; // 定义一个常量N,用于表示动态规划数组的大小
ll dp[N], B, ans; // dp[]: 动态规划数组,B: 可能用到的其他变量(未在代码中使用),ans: 最大化的目标价值

int main() {
    int n; // n表示任务的数量
    cin >> n; // 读取任务数量
    
    // 输入每个任务的等待时间、截止时间和价值
    for (int i = 1; i <= n; i++) {
        cin >> a[i].wait >> a[i].dead >> a[i].value;
    }
    
    // 按照截止时间从小到大对任务进行排序
    sort(a + 1, a + n + 1, [](lesson a, lesson b) {
        return a.dead < b.dead;
    });
    
    // 动态规划过程
    for (int i = 1; i <= n; i++) { // 遍历每个任务
        for (int j = a[i].dead; j >= a[i].wait; j--) { // 从任务的截止时间回溯到等待时间
            // 更新dp[j],考虑是否执行当前任务并跳过其等待时间,与不执行当前任务的情况比较取最大值
            dp[j] = max(dp[j - a[i].wait] + a[i].value, dp[j]);
            // 更新全局的最大价值
            ans = max(dp[j], ans);
        }
    }
    
    // 输出最大价值
    cout << ans << '\n';
}

Java 版本(仅供参考)

import java.util.*;

public class Main {
    static class Course {
        int de, jie, jia; // 截止时间、等待时间、含金量

        public Course(int de, int jie, int jia) {
            this.de = de;
            this.jie = jie;
            this.jia = jia;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(); // 读入课程数量

        Course[] courses = new Course[n + 1]; // 定义课程数组

        // 读入每门课程的信息
        for (int i = 1; i <= n; i++) {
            int de = scanner.nextInt();
            int jie = scanner.nextInt();
            int jia = scanner.nextInt();
            courses[i] = new Course(de, jie, jia);
        }

        Arrays.sort(courses, 1, n + 1, new Comparator<Course>() {
            @Override
            public int compare(Course a, Course b) {
                return a.jie - b.jie; // 按照截止时间升序排序
            }
        });

        long[][] dp = new long[n + 1][N]; // 定义动态规划数组

        // 动态规划过程
        for (int i = 0; i <= n; i++) {
            Arrays.fill(dp[i], 0);
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < N; j++) {
                dp[i][j] = dp[i - 1][j]; // 初始化当前状态为前一个状态
                if (j >= courses[i].jie && j - courses[i].de >= 0) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - courses[i].de] + courses[i].jia); // 状态转移方程
                }
            }
        }

        System.out.println(dp[n][courses[n].jie]); // 输出结果
    }

    static final int N = 100004; // 数组大小
}

Python 版本(仅供参考)

N = 100005

class Course:
    def __init__(self, de, jie, jia):
        self.de = de
        self.jie = jie
        self.jia = jia

if __name__ == "__main__":
    n = int(input()) # 读入课程数量
    courses = [None] * (n + 1) # 定义课程数组

    # 读入每门课程的信息
    for i in range(1, n + 1):
        de, jie, jia = map(int, input().split())
        courses[i] = Course(de, jie, jia)

    courses.sort(key=lambda x: x.jie) # 按照截止时间升序排序

    dp = [[0] * N for _ in range(n + 1)] # 定义动态规划数组

    # 动态规划过程
    for i in range(1, n + 1):
        for j in range(N):
            dp[i][j] = dp[i - 1][j] # 初始化当前状态为前一个状态
            if j >= courses[i].jie and j - courses[i].de >= 0:
                dp[i][j] = max(dp[i][j], dp[i - 1][j - courses[i].de] + courses[i].jia) # 状态转移方程

    print(dp[n][courses[n].jie]) # 输出结果

代码细节:

C++ 代码细节解释:

1. const int N = 1e5+10;
   定义了常量 N,用于表示数组的大小。
2. struct Course { int de, jie, jia; };
   定义了一个结构体 Course,用于表示课程的截止时间、等待时间和含金量。
3. bool cmp(Course a, Course b) { return a.jie < b.jie; }
   自定义了一个比较函数 cmp,用于对课程按照截止时间升序排序。
4. Course a[55];
   定义了课程数组,数组大小为 55。
5. cin >> n;
   从标准输入流读入课程数量。
6. cin >> a[i].de >> a[i].jie >> a[i].jia;
   依次读入每门课程的截止时间、等待时间和含金量。
7. sort(a + 1, a + n + 1, cmp);
   对课程数组按照截止时间进行排序。
8. long long dp[55][N];
   定义了动态规划数组 dp,用于存储动态规划过程中的状态。
9. for (int i = 0; i <= n; i++) { for (int j = 0; j < N; j++) { dp[i][j] = 0; } }
   初始化动态规划数组,将所有元素初始化为 0。
10. dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i].de] + a[i].jia);
   状态转移方程,表示当前状态下的最大含金量。

Java 代码细节解释:

1. class Course { int de, jie, jia; }: 
    这定义了一个名为`Course`的普通类,其中包含三个整数成员变量,表示课程的截止时间、等待时间和含金量。

2. static class Course { int de, jie, jia; ... }: 
    这定义了一个名为`Course`的静态嵌套类,与上述普通类类似。

3. Comparator<Course> cmp = new Comparator<Course>() { @Override public int compare(Course a, Course b) { return a.jie - b.jie; } };: 
    这创建了一个名为`cmp`的`Comparator`实例,用于按截止时间升序比较`Course`对象。

4. Course[] courses = new Course[n + 1];: 
    这声明了一个类型为`Course`的数组`courses`,大小为`n + 1`,用于存储每门课程的信息。

5. courses[i] = new Course(de, jie, jia);: 
    这初始化了一个新的`Course`对象,其截止时间、等待时间和含金量分别为给定的`de`、`jie`和`jia`值,并将其赋值给数组`courses`的第`i`个元素。

6. Arrays.sort(courses, 1, n + 1, cmp);: 
    这使用比较器`cmp`对从索引`1`到`n`的`courses`数组进行排序,排序依据是课程的截止时间`jie`,按升序排列。

7. long[][] dp = new long[n + 1][N];: 
    这声明了一个二维数组`dp`,用于存储动态规划过程中的状态,其中`dp[i][j]`表示考虑前`i`门课程且截止时间为`j`时的最大含金量。

8. for (int i = 0; i <= n; i++) { Arrays.fill(dp[i], 0); }: 
    这将数组`dp`中所有元素初始化为`0`,确保所有状态正确初始化。

9. dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - courses[i].de] + courses[i].jia);: 
    这是动态规划的状态转移方程,计算考虑第`i`门课程时的最大含金量,其中`j`为截止时间。它将当前最大含金量`dp[i][j]`与考虑截止时间为`j - courses[i].de`时的前`i - 1`门课程的最大含金量加上第`i`门课程的含金量`courses[i].jia`进行比较,选择较大者。

Python 代码细节解释:

1. N = 100005:
    这行代码定义了一个常量 N,用于表示数组的大小。

2. class Course::
    这行代码定义了一个名为 Course 的类。

3. def __init__(self, de, jie, jia)::
    这行代码定义了类的构造函数,初始化课程的截止时间、等待时间和含金量。

4. courses = [None] * (n + 1):
    这行代码定义了一个列表,用于存储课程对象。

5. courses.sort(key=lambda x: x.jie):
    这行代码对课程列表按照截止时间升序排序。

6. dp = [[0] * N for _ in range(n + 1)]:
    这行代码初始化了动态规划数组,将所有元素初始化为 0。

7. dp[i][j] = max(dp[i][j], dp[i - 1][j - courses[i].de] + courses[i].jia):
    这行代码是状态转移方程,表示当前状态下的最大含金量。它将当前最大含金量 dp[i][j] 与考虑截止时间为 j - courses[i].de 时的前 i - 1 门课程的最大含金量加上第 i 门课程的含金量 courses[i].jia 进行比较,选择较大者。

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。



笔记可能有点浅薄,误喷。

📚 《lenyan算法笔记》——探索算法的乐趣

🌟 欢迎来到《lenyan算法笔记》!这是我日常记录和分享算法学习心得的地方,无论你是初学者还是已经有一定经验的程序员,都能在这里找到有趣的内容。

🧠 记录学习心得:我用通俗易懂的语言记录了自己学习算法的过程和体会,希望能够帮助到更多有相同兴趣的朋友。

💻 分享实用代码:每篇笔记都附带了一些实用的代码示例,这些示例不仅是我学习的成果,也可以作为你学习的参考。

📈 持续学习进步:算法学习是一条持续的道路,我会不断地更新笔记内容,记录自己的学习进步,与你一起成长。

🔍 分享交流:如果你对我的笔记有任何疑问或建议,都欢迎在评论区与我交流,让我们一起探讨算法的乐趣!

🚀 如果你也对算法感兴趣,不妨点击链接,一起来探索《lenyan算法笔记》吧:《lenyan算法笔记》 🔥

lenyan算法笔记 · 语雀 《lenyan算法笔记》

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值