题目描述
思路
首先需要注意题目中的一些地方:天数是从1开始计数的,每个科目最多只依赖一个其它科目且依赖科目的编号必须小于自己,如果在n天内不能完成就不需要输出最晚开始时间。
求最早开始时间,要分为两种情况(关键在于当前科目是否有依赖):如果当前科目没有依赖,则最早开始时间就为1;如果当前科目有依赖,则最早开始时间为所依赖科目的最早开始时间+所依赖科目完成所需的时间,即earlyres[i]=earlyres[pre[i]]+days[pre[i]]。
求最晚开始时间,即最后一个科目完成时,恰好是最后一天,才能满足最晚开始时间的要求。需要从最后一个项目往前开始遍历(题目中指出:每项科目最多只依赖一项别的科目,且满足依赖科目的编号小于自己),如果当前项目没有依赖项目,则最晚开始时间只需要保证该科目可以按时完成,即lateres[i] =n-days[i]+1;如果当前科目有依赖,则需要对依赖项目的最晚开始时间进行更新,取最小值min(lateres[pre[i]],lateres[i]-days[pre[i]]),且开始需要将lateres数组值初始化为极大。
代码
C++版:
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n,m; // 距离大赛开幕的天数,训练科目数量
int pre[N];
int days[N];
int earlyres[N];
int lateres[N];
int main(){
int latest=0;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>pre[i];
}
for(int i=1;i<=m;i++){
cin>>days[i];
}
for(int i=1;i<=m;i++){
if(pre[i]==0) earlyres[i]=1;
else earlyres[i]=earlyres[pre[i]]+days[pre[i]]; // 最早开始时间
latest=max(latest,earlyres[i]+days[i]-1);// 判断能够全部完成训练,需要记录最后一项科目的完成时间
}
for(int i=1;i<=m;i++){
cout<<earlyres[i]<<" ";
}
cout<<endl;
if(latest>n) return 0;
memset(lateres,0x3f,sizeof(lateres)); // 初始化为无穷大
for(int i=m;i>0;i--){
if(lateres[i]>n) lateres[i]=n-days[i]+1; // 最晚开始时间
if(pre[i]!=0) lateres[pre[i]]=min(lateres[pre[i]],lateres[i]-days[pre[i]]); // 更新依赖节点的最晚开始时间
}
for(int i=1;i<=m;i++){
cout<<lateres[i]<<" ";
}
cout<<endl;
return 0;
}