CF1130 D1 D2:Toy Train

Toy Train

题目大意:有一辆玩具车和一个环形轨道,轨道有n个站点,玩具车沿着轨道前进,车子从第i站到第i+1站需要花费1s,第n站的下一站是第一站。给出m个搬运任务:把糖果从ai搬运到bi。每次经过一个站点,可以从这个站点搬运一个糖果,但只能搬运一个。车的容量有无限个,且每次可以卸下任意个糖果,装糖果和卸糖果的时间不记。现在问从各个点为起点出发,完成这m个任务的最小时间为多少。

一开始题目理解错了,首先想到:m个任务有ai和bi,所有的ai是有糖的站点,bi是放糖的站点。既然要最小时间,可不可以忽略糖果的真实来源,即实际上不是从ai搬到bi,而是从其他地方搬到bi,当然那个地方是从有糖的站点搬来的。想清楚题意后,这种解法于题目几乎无关。

既然要按题意的方式来,因为数据量并不大,想到了模拟,对ai bi 这样的输入 建一条bi到ai的边,然后 车经过每个结点,都从那个结点上装一个糖果到车上,并记录到数组。每到一个结点,遍历这个结点的所有任务结点,判断是否可以完成这条任务。这种解法复杂度为m*n^2,而且还是错的。按顺序处理所有的任务并不是最节约时间的。且复杂度太高。(代码还写错了,调了很久之后才发现错误的原因)

通过第二种解法,联想到如果ai站点要送糖果到多个站点,那么先送哪个后送哪个影响了整个任务的完成时间。如果用have[i]记录,i点有have[i]个糖果要送,那么从i点出发,至少要跑have[i]-1圈,那么执行任务的顺序,决定了最后一圈要跑的长度。既然have[i]-1 圈是必须要跑的 那么这have[i]-1次任务我们可以先完成离i比较远的,把最近的一个留到最后一圈,这样做是最省时间的。

再进一步,每一个点的任务是独立的,但是在同一圈可以同时完成,我们可以求完成各个点的任务的时间,取其中最大值,就是完成所有任务的时间解了。
贴出代码:

#include<iostream>
using namespace std;
#include<stdio.h>
#include<string.h>
#include<vector>
#define inf 0x3f3f3f3f
const int maxn = 1e5+10;
int n,m;
int ans[maxn];
int to[maxn];
int have[maxn];
int main(){
 	scanf("%d%d",&n,&m);
 	int x,y;
 	memset(to,0,sizeof(to));
 	memset(have,0,sizeof(have));
 	for(int i=1;i<=m;i++){
 		 scanf("%d%d",&x,&y);
  		 have[x]++;
  		if(to[x]==0) to[x]=y;
  		else{
   			if(to[x]>x&&y>x) to[x]=min(to[x],y);
   			if(to[x]<x&&y>x) to[x]=y;
   			if(to[x]<x&&y<x) to[x]=min(to[x],y);
  		}
 	}
 	for(int i=1;i<=n;i++)
 		if(to[i]<i) to[i]+=n;
 	for(int i=1;i<=n;i++){
  		int time=0;
  		for(int j=1;j<=n;j++){
  			if(have[j]){
    				int t=(have[j]-1)*n+(to[j]-j);
    				if(j<i) t+=j+n-i;
    				if(j>i) t+=j-i;
    				time=max(time,t);
   			}
  		}
  		ans[i]=time;
 	}
 	for(int i=1;i<=n;i++)
 		printf("%d ",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/88054428
d1
d2