20221202 训练计划思路
1. 计算最早开始时间
这一步比较简单
+ 对于没有依赖(即p[i]=0),f[i]=1,最早从第一天开始
+ 有依赖f[i]=f[p[i]]+t[p[i]] 依赖项目的最早+依赖的项目所需要的天数 ==(这里不需要减一,减一是依赖项目完成的时间)==
在处理最早时间的时候可以顺带判断训练是否能够在n天内完成
l[i] = n - ( f[i] + t[i]- 1 ) + 1; //项目最早开始时间+完成天数如果大于n则完不成
// f[i]+t[i]-1 是项目最早开始完成的时间 n - ~ + 1 加一是因为开始时间已经算训练了一天
if(l[i]<1) flag=1;
下面的操作是能够在n天完成的情况进行
2. 计算项目最晚的时间
首先要排序,数据结构是四元组,以项目依赖p
升序排列
struct task{
int i; //项目标号
int p; //项目依赖
int t; //项目时间
int l; //项目最晚开始时间
}a[N];
逆序倒着操作,这样每次计算的项目都只会被后面依赖
- 对于有依赖或既无依赖也无被依赖的项目, 在项目完成的时刻为n即可 ,
l[i] = n - t[i] + 1
- 被依赖的项目,求出依赖项目的最晚时间的最前一个(Min(l[k]),为了保证所有项目能够在n天内完成,需要求得最晚的最早的时间)再减去自己需要的天数
l[i] = Min ( l[k] ) - t[i]
- 有依赖且被依赖,本来需要考虑最晚开始时间是否大于依赖项目最晚结束时间,但是项目已经能够在n天内完成,就不需要考虑有依赖这一属性,只需要考虑被依赖这一情况。所以就归结到第二类处理
3. 最后一步,按项目序号排序即可
完整代码
#include<bits/stdc++.h>
const int N=110;
using namespace std;
int f[N],l[N];//f是最早开始的天数从1开始
struct task{
int i;
int p;
int t;
int l;
}a[N];
bool cmp(task &a,task &b)
{
return a.p<b.p;
}
bool cmp1(task &a,task &b)
{
return a.i<b.i;
}
int main()
{
int j,n,m,i,t[N],p[N],flag=0;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++) scanf("%d",&p[i]);//依赖的项目
for(i=1;i<=m;i++) scanf("%d",&t[i]);//所需天数
for(i=1;i<=m;i++)
{
//不依赖任何项目
if(p[i]==0)
{
f[i]=1;
//要分情况,优先级更高的是训练能够在n天内完成
l[i]=n-t[i]+1;
}
//依赖
else
{
int x,d=0;
x=p[i];
//求依赖前面所需要的时间
f[i]=f[p[i]]+t[p[i]];
l[i] = n - ( f[i] - 1 + t[i] ) + 1;
if(l[i]<1) flag=1;
l[i]=n-t[i]+1;
}
}
for(i=1;i<=m;i++)
{
printf("%d ",f[i]);
}
printf("\n");
if(!flag)
{
for(int i=1;i<=m;i++)
{
a[i].i=i;
a[i].p=p[i];
a[i].t=t[i];
a[i].l=l[i];
}
sort(a+1,a+m+1,cmp);
//更新l数组,使得训练能够在N天完成
//只需要更新p[i]=0.p[i]>0时已计算
//找到以自己为依赖 l 的最小值
for(int i=m;i>=0;i--)
{
int min=366;
for(int j=i+1;j<=m;j++)
{
if( a[j].p==a[i].i && min>a[j].l )
{
min=a[j].l;
}
if(a[j].p>a[i].i) break;
}
if(min<366) //若存在依赖
{
a[i].l=min-a[i].t;
}
}
sort(a+1,a+m+1,cmp1);
for(i=1;i<=m;i++)
printf("%d ",a[i].l);
printf("\n");
}
return 0;
}