算法笔记练习 3.1 简单模拟 问题 E: 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.

输入
Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 … 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 (<=104), 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 107.

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

样例输入

5 1 2 4 14 9
3
1 3
2 5
4 1

样例输出

3
10
7

思路

题目不难但是容易超时。不难想到相对暴力的解法:把所有N个出口之间的距离放在一个数组dis内,同时计算跑一整圈的距离sum,然后根据输入的出口编号计算正着跑和反着跑的距离,输出较小的结果即可。

但是这样的解法对于每一对输入都要以遍历的方式计算距离,如何节省时间?自然想到可以用空间换时间:

开另一个数组disToFirst来记录所有检查站到 1 号检查站的距离,这个数组中的距离都是正向距离,即从 1 号开始跑到 2 号,再到 3 号,直到 i 号检查站的距离之和即为disToFirst[i]。自然disToFirst[1]等于 0。

同时需要一个额外的变量finalToFirst来记录第 N 个检查站到第 1 个检查站的距离。

对于每一组输入ab,假设b > a(若不成立则交换ab),令从a正向跑到b的距离front等于disToFirst[b] - disToFirst[a],而反向的距离back就等于disToFirst[N] - front + finalToFirst,输出较小的那个距离即可。

代码

#include 

int main() {
	int N, M, a, b;
	while (scanf("%d", &N) != EOF) {
		int dis[N + 1], disToFirst[N + 1], finalToFirst;
		disToFirst[1] = 0;
		for (int i = 2; i <= N; ++i) {
			scanf("%d", &dis[i]);
			disToFirst[i] = disToFirst[i - 1] + dis[i];
		}
		scanf("%d", &finalToFirst);
		scanf("%d", &M);
		while (M--) {
			scanf("%d%d", &a, &b);
			if (a > b) {
				int temp = a;
				a = b;
				b = temp;
			}
			int front = disToFirst[b] - disToFirst[a];
			int back = disToFirst[N] - front + finalToFirst; 
			printf("%d\n", front < back ? front : back);
		} 
	}
	return 0;
} 

你可能感兴趣的:(算法笔记)