题解:P13898 [CSPro 28] 训练计划
题目传送门
计算每个科目的最早开始时间和最晚开始时间。依赖关系要求一个科目必须在它所依赖的科目完成后才能开始。
问题要求计算每个科目的最早和最晚开始时间。依赖关系是树形结构,且科目编号有序。
最早开始时间:对于每个科目,如果没有依赖
最晚开始时间:需要逆向处理。首先检查所有科目是否能在
对于最晚开始时间,考虑依赖关系:一个科目的延迟会影响所有依赖它的科目。因此需要从后向前处理。对于科目
整理成步骤:
- 计算最早开始时间:使用动态规划从前向后处理,因为每个科目的依赖科目编号小于自己。
- 检查可行性:计算每个科目的最早结束时间,如果所有结束时间
\le n ,则可行。 - 计算最晚开始时间:使用逆向动态规划。对于每个科目
i ,计算所有依赖它的科目j 的最晚开始时间减去t_i (因为科目i 必须在科目j 开始前完成)的最小值。
CODE:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e2+5;
int n,m,p[N],t[N],ea[N],la[N],chi[N][N],cnt[N];
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>p[i];
for(int i=1;i<=m;i++)
cin>>t[i];
for(int i=1;i<=m;i++)
if(p[i]==0)
ea[i]=1;
else
ea[i]=ea[p[i]]+t[p[i]];
bool f=true;
for(int i=1;i<=m;i++)
if(ea[i]+t[i]-1>n){
f=false;
break;
}
for(int i=1;i<=m;i++)
cout<<ea[i]<<" ";
cout<<endl;
if(!f)
return 0;
for(int i=1;i<=m;i++)
if(p[i]!=0)
chi[p[i]][cnt[p[i]]++]=i;
for(int i=m;i>=1;i--)
if(cnt[i]==0)
la[i]=n-t[i]+1;
else{
int minx=1e9;
for(int j=0;j<cnt[i];j++)
if(la[chi[i][j]]-t[i]<minx)minx=la[chi[i][j]]-t[i];
la[i]=minx;
}
for(int i=1;i<=m;i++)
cout<<la[i]<<" ";
return 0;
}