CCF-CSP 202212-2 训练计划
子任务
-
70 % 70\% 70%的测试数据满足:顿顿无法在 n n n天 内完成全部 m m m 项科目的训练,此时仅需输出一行“最早开始时间”;
-
全部的测试数据满足 0 < n ≤ 365 0<n\leq365 0<n≤365 且 0 < m ≤ 100 0<m\leq100 0<m≤100 。
题目背景
本题的题目背景是AOE网。



在上述AOE网中,ve 表示最早开始时间,vl 表示最迟开始时间。事件
k
k
k 的最早开始时间
v
e
(
k
)
ve(k)
ve(k),是从源点到顶点
k
k
k 的最长路径长度。最迟开始时间
v
l
(
k
)
vl(k)
vl(k) 等于整个工程的关键路径从源点到汇点的最长路径)长度减去从顶点
k
k
k 到汇点的最长路径的长度。
(参考《数据结构:抽象建模、实现与应用》孙涵,黄元元,高航,秦小麟编著.机械工业出版社,2020 p. 113-126)
解题思路
针对子任务1,思路较为简单,不过多赘述。要通过所有样例,难点在于计算出最迟开始时间,解题步骤如下:
- 计算出样例是否能在规定的 n n n 天内完成项目训练
- 若不能,仅输出最早开始时间
- 若能,计算各项目的被依赖关系(eg,项目j依赖于项目i,则i需要先完成,再完成j,被依赖关系是项目i被j依赖)
- 若项目i被j依赖,最迟开始时间的计算公式为:
vl[i]=min(vl[j]-day[i],vl[i]); - 若项目i没有存在被依赖关系,则最迟开始时间的计算公式为:
vl[i]=max_day-day[i]; - 注意,因为项目训练首天为第一天,所以
max_day=n+1;
满分题解
#include <iostream>
using namespace std;
#include <unordered_map>
#include <vector>
int p[101];
int ve[101];
int vl[101];
int day[101];
unordered_map<int,vector<int>> q;
int main(int argc, char const *argv[])
{
int n,m;
int max_day = -1;
bool flag = true;
cin >> n >> m;
int i,j;
// 依赖关系
for (i = 1; i <= m; i++)
{
cin >> p[i];
}
for (i = 1; i <=m; i++){
cin >> day[i];
if (p[i]){
ve[i]+=ve[p[i]]+day[p[i]];
}
else{
ve[i] = 1;
}
max_day = max(ve[i]+day[i],max_day); // 更新关键路径长度
}
for (i = 1; i<=m;i++)
{
cout << ve[i] << " ";
}
if (max_day > n+1){
// 无法完成任务
flag = false;
return 0;
}
max_day = n+1;
cout << endl;
// 可以完成任务,下面计算最晚开始时间
// 被依赖关系
for (i = 1; i <= m; i++){
if (p[i]){
// i依赖于p[i]
// p[i]被i依赖
q[p[i]].push_back(i);
}
}
// 逆向计算最早开始时间
for (i = m; i > 0; i--){
if (q[i].empty()){
// 说明没有科目依赖于科目i
// 科目i的最迟开始时间为:max_day-day[i]
vl[i] = max_day - day[i];
continue;
}
// 存在被其他科目依赖的关系
vl[i] = INT32_MAX;
for (auto it : q[i])
{
vl[i] =min(vl[it]-day[i],vl[i]);
}
}
for (i = 1; i <= m; i++){
cout << vl[i] << " ";
}
return 0;
}
1678

被折叠的 条评论
为什么被折叠?



