目录
lenyan算法笔记 · 语雀 《lenyan算法笔记》
个人笔记日常更新。含金量不高。/(ㄒoㄒ)/~~
题目
思路和解题方法
- 首先,定义了一个结构体
Course
来表示每门课程的截止时间、等待时间和含金量。- 在
main
函数中,首先读入课程数量n
,然后读入每门课程的信息,并将它们按照截止时间升序排序。- 接下来,定义了一个二维数组
dp
,其中dp[i][j]
表示在前i
门课程中,截止时间为j
时能够获得的最大含金量。- 初始化
dp
数组,将所有元素置为 0。- 接着,进行动态规划的状态转移。对于每一门课程
i
,遍历所有可能的截止时间j
,更新dp[i][j]
:
- 如果当前时间
j
大于等于课程i
的截止时间,并且从当前时间往前推等待时间仍然在有效范围内,则尝试将课程i
加入购买考虑,并更新dp[i][j]
。- 在更新
dp[i][j]
时,可以选择将课程i
加入购买考虑或不加入,取两者中含金量更高的那个。- 最终,输出
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算法笔记》