题目
测试满分![](https://img-blog.csdnimg.cn/775c263bff354d5db82adbd6221ce35f.png)
代码示例
#include <iostream>
#include <bits/stdc++.h>
using namespace std;int main()
{
int n,m;
cin >> n >> m;
int rel[m+1];
int need_day[m+1];
for(int i=1; i<=m; i++)
{
cin >> rel[i];
}
for(int i=1; i<=m; i++)
{
cin >> need_day[i];
}
int early_time[m+1];
int dead_time[m+1];
for(int i=0; i<=m; i++)
{
early_time[i]=1;
dead_time[i]=n;
}
//计算最早时间
for(int i=1; i<=m; i++)
{
if(rel[i]==0)
{
early_time[i]=1;
}
else
{
early_time[i]=early_time[rel[i]]+need_day[rel[i]];
}
}
//计算最晚开始时间
for(int i=m; i>0; i--)
{
dead_time[i]=min(n-need_day[i]+1,dead_time[i]);
dead_time[rel[i]]=min(dead_time[i]-need_day[rel[i]],dead_time[rel[i]]);
}
int tag=1;
for(int i=1; i<=m; i++)
{
if(dead_time[i]<=0)
{
tag=0;
break;
}
}
for(int j=1; j<=m; j++)
{
cout << early_time[j] << " ";
}
if(tag)
{
cout<<endl;
for(int j=1; j<=m; j++)
{
cout << dead_time[j] << " ";
}
}
return 0;
}
思路
说一下思路吧,其实刚开始我想复杂了,我以为他们之间的依存关系是复杂的,比如像1<—3<—2 这种,那其实用顺序遍历的时候遍历到了比前面的依存数小的时候,就需要调整到最开始的不存在依存关系的那个点,这时我想到了用递归的方法,因为递归的本质就是栈啦,但是后来我看见了文中最关键的一句话:“每个科目最多只依赖一项别的项目,且满足依赖科目的编号小于自己”,那这句话就让题目变得简单了,在求最早开始时间的时候,只要依次把编号小的确定了就好了,编号大的只不过是在小的上面有所参考罢了。同样在算最晚开始时间的时候,采用从后往前的思路,把编号大的确定,编号小的就依次往后挪动时间就好了。
下面说说求最早开始时间和最晚开始时间的思路吧。
1、最早开始时间
//计算最早时间
for(int i=1; i<=m; i++)
{
if(rel[i]==0)
{
early_time[i]=1;
}
else
{
early_time[i]=early_time[rel[i]]+need_day[rel[i]];
}
}
计算最早开始时间的话,如果该科目不存在依赖科目,那就直接最早从第一天就可以开始了,如果存在依赖科目的话,那就要以依赖科目的最早开始时间为基线,加上依赖科目完成所需时间,那么就是这个科目的最早开始时间了。
2、最晚开始时间
//计算最晚开始时间
for(int i=m; i>0; i--)
{
dead_time[i]=min(n-need_day[i]+1,dead_time[i]);
dead_time[rel[i]]=min(dead_time[i]-need_day[rel[i]],dead_time[rel[i]]);
}
计算最晚开始时间的话,最晚时间不能超过最后一天,所以我们以最后一天为基线,从编号大的开始计算他的最晚开始时间,这个时候就涉及到了两个问题:(1)当该科目已经被其他科目依赖的时候 ,我们在计算它的最晚开始时间的时候就需要有一个最小值的比较,比较它在别人的约束条件下的时间和自己本身的约束时间那个更小。(2)当一个科目同时被多个科目依赖的时候,我们需要取比较小的时间作为最晚开始时间。这个时候,有可能某些科目的最晚开始时间已经小于0了,就说明无法完成训练任务,这也是我们控制输出几行的标准了。
总结
总结就是这次的第二题比以往的简单些啦,如果把“每个科目最多只依赖一项别的项目,且满足依赖科目的编号小于自己”这两句随便改一下,比如“每个科目可依赖多个项目”或是“依赖科目的编号不一定小于自己”,亦或者是两个条件也要满足,那这个题就难了,可以作为csp的第四题的难度了。