算法笔记练习 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 <cstdio>

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;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值