第28次csp认证T2 训练计划
题目说明
问题链接:http://118.190.20.162/view.page?gpid=T159
题目详解
这个题的难点就在于如何求最早开始时间和最晚开始时间。有个细致的点就在于一个训练任务最多只对应一个前置任务,而一个任务可能作为多个任务的前置任务。因此我们写的算法就要考虑进这种情况。再一点计算时间的时候,需要+1再减之前的天数,因为训练的第一天也要算进去。
对于最早开始时间,没有前置条件的就是1,有前置条件的,就是前置条件的开始天+活动持续天数。要注意此时计算下当前任务是否能完成,如果存在任何一个不能完成的任务,就需要把bool变量置false,不求最晚开始时间了。
对于最晚开始时间,从后向前遍历。先把最晚时间都置成最大数如999,从后往前计算,对每个i的最晚开始时间都赋成n+1-活动持续时间,把它当成最后一个活动,然后看看该活动有没有前置活动,计算出来前置活动的潜在(可能)最晚开始时间,这个时间和目前最晚的时间比较,取一个更早的时间作为前置活动的最晚开始时间,这样遍历一遍即可得到正确答案。
满分代码
#include<bits/stdc++.h>
using namespace std;
int pre[105];
int days[105];
int early[105];
int least[105];
bool cancomplete = true;
int m,n;
int main(){
cin>>n>>m;
for(int i=0;i<m;i++) cin>>pre[i];
for(int i=0;i<m;i++) cin>>days[i];
for(int i=0;i<m;i++){
if(pre[i]==0){
early[i] = 1;
if(early[i]+days[i]-1>n) cancomplete = false;
}
else{
early[i] = early[pre[i]-1]+days[pre[i]-1];
if(early[i]+days[i]-1>n) cancomplete = false;
}
cout<<early[i]<<" ";
}
cout<<endl;
for(int i=0;i<m;i++) least[i]=999;
if(cancomplete){
for(int i=m-1;i>=0;i--){
if(least[i]==999)
least[i] = n+1 - days[i];
if(pre[i]!=0){
int newleast = least[i] - days[pre[i]-1];
if(least[pre[i]-1]>newleast){
least[pre[i]-1]=newleast;
}
}
}
for(int i=0;i<m;i++) cout<<least[i]<<" ";
}
}