PAT 1046 Shortest Distance(20 分)
题目描述
The task is really simple: given N N 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 N N ( i n [ 3 , 1 0 5 ] ) (in [3,10^5]) (in[3,105]), followed by N N N integer distances D 1 D 2 … D N D_1 D_2 \dots\ D_N D1D2… DN, where D i D_i Di is the distance between the i i i-th and the ( i + 1 ) (i+1) (i+1)-st exits, and D N D_N DN is between the N N N-th and the 1 1 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M ( ≤ 1 0 4 ) M (≤10^4) M(≤104), with M M M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 1 1 to N N N. It is guaranteed that the total round trip distance is no more than 1 0 7 10^7 107.
输出
For each test case, print your results in M M 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
思路
根据题意容易知道:
- 所有公路构成了一个首尾相连的路径圈
- 从每个点出发,只能往前走或者往后走来到达目的地
现在假设有一个环绕的路径圈
A
−
B
−
C
−
D
−
E
−
F
−
G
−
A
A-B-C-D-E-F-G-A
A−B−C−D−E−F−G−A,所有路径构成的路径圈总长度为
t
o
t
a
l
=
a
b
+
b
c
+
c
d
+
d
e
+
e
f
+
f
g
+
g
a
total = ab + bc +cd + de + ef + fg + ga
total=ab+bc+cd+de+ef+fg+ga。
假设我们要从点
B
B
B到达点
F
F
F,首先考虑从点
B
B
B向后搜索到达点
F
F
F(路径1)的距离为
b
c
+
c
d
+
d
e
+
e
f
bc + cd + de + ef
bc+cd+de+ef,而从点
B
B
B向前搜索到达点F(路径2)的距离为
f
g
+
g
a
+
a
b
fg + ga + ab
fg+ga+ab。
可以发现,最短的路径长度是从路径1与路径2的比较中产生的。
而路径1的长度我们可以通过前缀和的方式求得,路径2的长度则是总的路径圈的长度减去路径1的长度。
通过这个例子,我们掌握了求解这道题的核心思想,下面是我的示例代码。
代码
#include <iostream>
using namespace std;
int main(void){
//total为整个路径循环的总体长度
int N, M, total = 0;
//path用来记录路径1至路径N的长度
//sum为路径的前缀和数组
int path[100005], sum[100005];
cin>>N;
//输入路径值的同时,更新路径圈的长度和前缀和数组
for(int i = 1; i <= N; i++){
scanf("%d", &path[i]);
total += path[i];
sum[i] = sum[i - 1] + path[i];
}
cin>>M;
while(M--){
int a, b;
cin>>a>>b;
//因为采用了前缀和,所以将其交换,保证始终是b为索引大的一方,减去索引更小的a
if (a > b) swap(a, b);
//通过前缀和之差来求得两点之间的距离
int temp = sum[b - 1] - sum[a - 1];
//求出的前缀和之差为temp,路径圈长度为total,则较短的距离从temp和total-temp中产生
int ans = min(temp, total - temp);
cout<<ans<<endl;
}
return 0;
}
结语
今天看到这道题觉得特别有意思,故此将解法记录下来。希望能够帮到各位!写的第二篇博文了!不得不说学习新事物确实能够让人感到快乐!暑假紧张兮兮地准备预推免,希望能够顺利保研!也祝所有读者生活开心,学业顺利噶!