问题背景
西西艾弗岛荒野求生大赛还有 � 天开幕!
问题描述
为了在大赛中取得好成绩,顿顿准备在 � 天时间内完成“短跑”、“高中物理”以及“核裂变技术”等总共 � 项科目的加强训练。其中第 � 项(1≤�≤�)科目编号为 �,也可简称为科目 �。已知科目 � 耗时 �� 天,即如果从第 � 天开始训练科目 �,那么第 �+��−1 天就是该项训练的最后一天。
大部分科目的训练可以同时进行,即顿顿在同一天内可以同时进行多项科目的训练,但部分科目之间也存在着依赖关系。如果科目 � 依赖科目 �,那么只能在后者训练结束后,科目 � 才能开始训练。具体来说,如果科目 � 从第 � 天训练到第 �+��−1 天,那么科目 � 最早只能从第 �+�� 天开始训练。还好,顿顿需要训练的 � 项科目依赖关系并不复杂,每项科目最多只依赖一项别的科目,且满足依赖科目的编号小于自己。那些没有任何依赖的科目,则可以从第 1 天就开始训练。
对于每一项科目,试计算:
1)最早开始时间:该科目最早可以于哪一天开始训练?
2)最晚开始时间:在不耽误参赛的前提下(� 天内完成所有训练),该科目最晚可以从哪一天开始训练?
� 天内完成所有训练,即每一项科目训练的最后一天都要满足 ≤�。需要注意,顿顿如果不能在 � 天内完成全部 � 项科目的训练,就无法参加大赛。这种情况下也就不需要再计算“最晚开始时间”了。
输入格式
从标准输入读入数据。
输入共三行。
输入的第一行包含空格分隔的两个正整数 � 和 �,分别表示距离大赛开幕的天数和训练科目的数量。
输入的第二行包含空格分隔的 � 个整数,其中第 � 个(1≤�≤�)整数 �� 表示科目 � 依赖的科目编号,满足 0≤��<�;��=0 表示科目 � 无依赖。
输入的第三行包含空格分隔的 � 个正整数,其中第 � 个(1≤�≤�)数 �� 表示训练科目 � 所需天数,满足 1≤��≤�。
输出格式
输出到标准输出中。
输出共一行或两行。
输出的第一行包含空格分隔的 � 个正整数,依次表示每项科目的最早开始时间。
如果顿顿可以在 � 天内完成全部 � 项科目的训练,则继续输出第二行,否则输出到此为止。
输出的第二行包含空格分隔的 � 个正整数,依次表示每项科目的最晚开始时间。
这道题一反常态,有点太简单了哈哈,不太适应。作为考试前的最后一道第二题练习,记录一下。
这道题基础70分没问题的。
一个训练的开始时间只和它是否需要依赖有关。依赖,则开始时间在被依赖项的开始时间上加上被依赖项的练习时间;不依赖,则开始时间为1。其中如果开始时间+练习时间>n,则说明不能在时间内完成,只需要输出开始时间。
一个训练的最迟开始时间:如果不依赖,则为距离大赛开幕的天数n+1-练习时间。
但是如果依赖呢?
首先,题目中说0<=pi<i,意味着整体结构是很多棵树,如果依赖,则成为被依赖项的叶子结点之一。注意这个之一,这意味着一棵树可能有0个或多个叶子结点。
一个结点一旦有叶子结点,意味着它的最迟开始时间需要提前,提前的时间则为叶子结点中最长需要花费的时间。
这么解释吧,如果这个叶子结点下没有叶子结点,则这个叶子结点需要花费的最长时间就是它本身的练习时间。递推上它的父结点,父结点需要花费的时间就是父结点的练习时间+其子结点中需要花费的最长时间。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct p{
int s=0;
int e=0;
int d;
};
int main(){
int n,m;
cin>>n>>m;
int flag=0;
p p_s[m+1];
int days[m+1];
int tempday[m+1];
for(int i=1;i<=m;++i){
cin>>p_s[i].d;
}
for(int i=1;i<=m;++i){
cin>>tempday[i];
days[i]=0;
}
//对于被依赖的项,最晚完成的时间需要提前,现在的问题是提前多少。
//从叶节点入手,选取完成时间最长的叶节点为提前的时间。
//由于0<=pi<i,所以回溯
for(int i=m;i>=1;--i){
days[i]+=tempday[i];
if(p_s[i].d!=0){
days[p_s[i].d]=max(days[i],days[p_s[i].d]);
}
}
for(int i=1;i<=m;++i){
p_s[i].e=n-days[i]+1;
if(p_s[i].d==0){
p_s[i].s=1;
}
else{
p_s[i].s=p_s[p_s[i].d].s+tempday[p_s[i].d];
if(p_s[i].s+tempday[i]>n){
flag=1;
}
}
}
for(int i=1;i<=m;++i){
cout<<p_s[i].s<<" ";
}
cout<<endl;
if(flag==0){
for(int i=1;i<=m;++i){
cout<<p_s[i].e<<" ";
}
}cout<<endl;
}