PAT A1046. Shortest Distance (20)

1046 Shortest Distance (20 分)

The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

Input Specification:
Each input file contains one test case. For each case, the first line contains an integer N (in [3,10^​ ]), followed by N integer distances D​1D2⋯ DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (≤10^​4), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 10^7.

Output Specification:
For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.

Sample Input:
5 1 2 4 14 9
3
1 3
2 5
4 1
Sample Output:
3
10
7
时间限制
200 ms

内存限制
64 MB

题意:

有N个结点围成一个圈,相邻两个结点的距离已知,求A结点到B结点的最短距离(计算顺时针距离和逆时针距离输出较小者)。

思路1:

int型变量N接收结点数,int型数组num接收各结点的距离(num[1]存放1-2的距离),sum存放一周的路径,int型变量M存放要查询的组数,a,b存放查询的两个结点编号,distance1存放顺时针距离,distance2存放逆时针距离。
外层for循环不断接收结点,里层循环计算顺时针逆时针距离,最后输出最小的距离。

参考代码1:

#include <cstdio>
int main(){
	int N;
	scanf("%d",&N);
	int num[N+1];//存放输入的距离(num[1]代表1-2的距离); 
	int sum=0;
	for (int i=1;i<=N;i++){
		scanf("%d",&num[i]);
		sum+=num[i];
	}
	int M;
	scanf("%d",&M);
	int a,b;
	for (int i=0;i<M;i++){
		scanf("%d %d",&a,&b);
		int distance1=0,distance2=0;
		if(a<b){
			for (int j=a;j<b;j++){
				distance1+=num[j];
				distance2=sum-distance1;
			}
		}
		else{
			for(int j=b;j<a;j++){
				distance1+=num[j];
				distance2=sum-distance1;
			}
		}
		if(distance1<distance2) printf("%d\n",distance1);
		else printf("%d\n",distance2);
	} 
	return 0;
}

此代码最后一个样例点运行超时,因为在极端情况下,每次查询要遍历整个数组,10^5 次操作,计算距离最多要10^4次操作,在200ms是完成不了的。

思路2:

大体跟思路1一致,只不过用了int型数组distance存储距离,distance[i]代表第一个结点到第i个结点顺时针距离。至于任意两个结点a,b(b>a)间的顺时针距离则是distance[b]-distance[a];

参考代码2:

#include <cstdio>
int main(){
	int N;
	scanf("%d",&N);
	int num[N+1];//存放输入的距离(num[1]代表1-2的距离); 
	int sum=0;
	int distance[N+1];
	for (int i=1;i<=N;i++){
		scanf("%d",&num[i]);
		distance[i]=sum;//distance[i]代表从第1个结点到第i个结点的顺时针距离;
		sum+=num[i];
		 
	}
	int M;
	scanf("%d",&M);
	int a,b;
	for (int i=0;i<M;i++){
		int distance1=0,distance2=0;
		scanf("%d %d",&a,&b);
		if(a<b){
			distance1=distance[b]-distance[a];
			distance2=sum-distance1;	
		} 
		else{
			distance1=distance[a]-distance[b];
			distance2=sum-distance1;
		}
		if(distance1<distance2) printf("%d\n",distance1);
		else printf("%d\n",distance2);
	}
	return 0;
}

点评:

①此题属于简单模拟型,英文题意也较好理解,按题意翻译即可。
②注意程序的时间复杂度,O(n^2)是不能满足通过要求的,很容易想到空间换时间的策略,用distance数组存储距离。
③注意题目中表明的N,M范围,不难想到此题可能考查关于时间复杂度优化问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值