写在所有的前面:
本文采用C++实现代码
目录
题目说明
题目:带权区间调度(Weighted Interval Scheduling)
题目出处
广西大学oj
22级《算法设计与分析》第二次课堂作业
https://oj.gxu.edu.cn/contest/625/problem/0004
题目描述Description
背每一个任务都有三个属性:开始时间s、结束时间f以及所产生的价值v一个任务的s到f这段时间称为其执行时间,如果两个任务的执行时间不重叠,则称它们是兼容的本题将给出若干任务及其属性,求彼此兼容且权重最大的任务子集,输出该子集所有任务产生的总价值。
输入Input
输入有1+n行;第1行为任务数量;剩余n行每行为一个任务的开始时间、结束时间和所产生的价值,以空格隔开
输出Output
输出应为一个数,即彼此兼容且权重最大的任务子集中所有任务产生的总价值
样例Sample
输入:
4
1 2 50
3 5 20
6 19 100
2 100 200
输出:
250
限制Hint
解答说明
方案1:动态规划
解题思路
背包问题的变种:本人写的《(C++)0-1背包问题(动态规划)》
https://blog.csdn.net/just_do_it_sq/article/details/142499586?spm=1001.2014.3001.5501
总共n个任务,m时间最大值(终止时间数组 f 的最大值作为所有任务的终止时间)
通过 sumv[i][j] 记录执行前 i 个任务,时间为 j 时,所拥有的最大总价值
遍历每一个 i 和 j 来实现对 sumv 的填充
最后输出 sumv[n][m] 即可
一般情况
当任务 i 无法被执行完毕时j < f[i]
,和执行上一个任务时一样sumv[i][j] = sumv[i - 1][j];
否则掏出对应执行时间的任务,查看当时的最大总价值 + 当前任务价值 与 执行上一任务方案相比,哪个更总价值更大sumv[i][j] = max(sumv[i - 1][j], sumv[i - 1][s[i]] + v[i]);
特殊情况
初始化:没有任务( i == 0
)和没有时间( j == 0
)时,sumv 为 0
代码实现
#include<iostream>
#include <algorithm>
using namespace std;
const int N = 100;//常量
int n;//任务数量
int s[N], f[N], v[N];//开始时间,结束时间,价值
int sumv[N][100 * N];//最大总价值,max[i][j] 代表执行前 i 个任务,时间为 j 时
int main()
{
//输入数据
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d%d", &s[i], &f[i], &v[i]);
}
//终止时间数组 f 的最大值作为所有任务的终止时间
int m = *max_element(f + 1, f + 1 + n);
//计算最大总价值
for (int i = 1; i <= n; i++) //执行前 i 个任务
{
for (int j = 1; j <= m; j++) //时间增大为 j
{
if (j < f[i])//执行不完
sumv[i][j] = sumv[i - 1][j];//和执行上一件任务时一样
else//装得进去
//掏出对应时间的任务,查看当时的最大总价 + 当前任务价值 与 执行之前方案相比,哪个更总价更大
sumv[i][j] = max(sumv[i - 1][j], sumv[i - 1][s[i]] + v[i]);
}
}
//全部任务全部时间时最大价值
printf("%d", sumv[n][m]);
return 0;
}
其他解释
求数组最大值
*max_element(arr + m, arr + n)
,调用头文件#include <algorithm>
,返回两个指针间数据的最大值,即arr[m]到arr[n]之间的最大值,最小值将max换为min即可