第28次csp认证T2 训练计划题目详解

第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]<<" ";
}
} 

猜你喜欢

转载自blog.csdn.net/Sunnyztg/article/details/129511732