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 ABCDEFGA,所有路径构成的路径圈总长度为 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;
}

结语

今天看到这道题觉得特别有意思,故此将解法记录下来。希望能够帮到各位!写的第二篇博文了!不得不说学习新事物确实能够让人感到快乐!暑假紧张兮兮地准备预推免,希望能够顺利保研!也祝所有读者生活开心,学业顺利噶!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值