关键词:任务安排、贪心、时间单调性(起始/截止时间随任务排序单调变化)
题意:a、b间有一条路径,每次只能有一辆车通行,每辆车通行时间为1分钟。已知准备好从a端出发车辆的时间t和该车通行该道路最多花费时间p,即该车在[t,t+p-1]时间内必须发车!b端同理。要求发车每一起点的发车顺序必须按照输入的顺序进行,输入顺序保证i< j,ti<=tj。
现在问是否有一种发车方案,使得每辆车都能顺利到达目的地。
解法:
1.从发车顺序条件出发:前一辆车的发车时间一定早于后一辆车,因此前一辆车的最晚发车时间一定早于后一辆车的最晚发车时间。因此:
bus[i].lastbegin=min(bus[i].t+bus[i].p−1,bus[i+1].lastbegin)
2.现在可得到同侧发车按顺序最早发车时间和最晚发车时间均递增。贪心思路:如果当前a-> b的最早发车时间为x1,最晚发车时间为x2,b->a的最早发车时间为y1,最晚发车时间为y2。
1)如果x1!=y1。那么小的那个先出发对大的不产生影响,因而对整体发车情况不产生影响。
2)如果x1==y1。x2!=y2时,一定小的先出发,因为每边的最晚发车时间都是递增的,所以x2和y2中小的最晚发车时间最靠前,因此需要先发车。
3)如果x1==y1&&x2==y2,这两辆车都需要在x2(或y2)之前发车,又因为剩下所有车的最晚发车时间都不小于x2(或y2),因此这两辆车都必须在剩下所有车发车之前发车,所以哪个先发车对能够成功安排通行的结果无影响!此时任意一个发车都可以。
现在问题是如何求当前车辆的最早和最晚发车时间?
最晚发车时间在1中已求出。求当前车辆的最早发车时间需要知道上次发车时间,因此需要用cur记录上次的发车时间,那么:
bus[i].earlybegin=max(bus[i].t,cur+1).
本题难点在于想到维护上次发车时间,以及预处理每辆车的最晚发车时间
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<limits.h>
#include<queue>
#include<vector>
#define mem(a,b) memset(a,sizeof(a),b)
#define ll long long
#define MP make_pair
const ll INF = 0x0fffffffffffffff;
using namespace std;
typedef long long lld;
const int maxn = 100000+10;
/*
int read(){//读入优化 结果时间更长了。
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
return x*f;
}*/
struct Node{
int l,r;//l:最早出发时间;r:最晚出发时间
}bus1[maxn],bus2[maxn];
int n,m;
int Min(int a,int b){ return (a<b)?a:b; }
int Max(int a,int b){ return (a<b)?b:a; }
int main(){
//freopen("a.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++){
int dis;
//bus1[i].l=read(),dis=read();
scanf("%d%d",&bus1[i].l,&dis);
bus1[i].r=bus1[i].l+dis-1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int dis;
//bus2[i].l=read(),dis=read();
scanf("%d%d",&bus2[i].l,&dis);
bus2[i].r=bus2[i].l+dis-1;
}
//计算每辆车的最晚出发时间---预处理很关键!
for(int i=n-1;i>=1;i--) bus1[i].r=Min(bus1[i].r,bus1[i+1].r-1);
for(int j=m-1;j>=1;j--) bus2[j].r=Min(bus2[j].r,bus2[j+1].r-1);
int i,j;
int cur=0;//记录上次的发车时间---以前的最晚发车时间(用来更新下次每辆车的最早发车时间)
bool flag=true;
for(i=1,j=1;i<=n&&j<=m;){
if((cur+1>bus1[i].r)||(cur+1>bus2[j].r)){
flag=false; break;
}
int tmpi=Max(cur+1,bus1[i].l),tmpj=Max(cur+1,bus2[j].l);//双向最早出发时间
if(tmpi<tmpj) { cur=Max(cur+1,tmpi); i++; }
else if(tmpi>tmpj) { cur=Max(cur+1,tmpj); j++; }
else{
if(bus1[i].r<bus2[j].r) { cur=Max(cur+1,tmpi); i++; }
else { cur=Max(cur+1,tmpj); j++; }
}
}
for(;flag&&i<=n;){
if(cur+1>bus1[i].r) { flag=false; break; }
cur=Max(cur+1,bus1[i].l);
i++;
}
for(;flag&&j<=m;){
if(cur+1>bus2[j].r) { flag=false; break; }
cur=Max(cur+1,bus2[j].l);
j++;
}
if(flag) printf("YES\n");
else printf("NO\n");
return 0;
}