AtCoder题解——Beginner Contest 160——C - Traveling Salesman around Lake

题目相关

题目链接

AtCoder,https://atcoder.jp/contests/abc160/tasks/abc160_c

Problem Statement

There is a circular pond with a perimeter of K meters, and N houses around them.

The i-th house is built at a distance of Ai meters from the northmost point of the pond, measured clockwise around the pond.

When traveling between these houses, you can only go around the pond.

Find the minimum distance that needs to be traveled when you start at one of the houses and visit all the N houses.

Constraints

  • 2 ≤ K ≤ 10^6
  • 2 ≤ N ≤ 2×10^5
  • 0 ≤ A1 < ... < AN < K
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

K N
A1 A2 ... AN

Output

Print the minimum distance that needs to be traveled when you start at one of the houses and visit all the N houses.

Samples1

Sample Input 1

20 3
5 10 15

Sample Output 1

10

Explaination

If you start at the 1-st house and go to the 2-nd and 3-rd houses in this order, the total distance traveled will be 10.

Samples2

Sample Input 2

20 3
0 5 15

Sample Output 2

10

Explaination

If you start at the 2-nd house and go to the 1-st and 3-rd houses in this order, the total distance traveled will be 10.

题解报告

本题含义

虽然是英文题,但是涉及的单词不多。基本意思就是一个圆形的湖边周长为 K,湖边上有 N 个房子,第 i 个房子到正北方的距离记为 Ai。然后有一个商人,要访问这 N 个房子。要求我们寻找一个最短的访问距离。

样例数据分析

其实这就是一个数学题。我们知道每两个房子之间的距离可以看成一个线段。这样,我们 N 个房子可以构成 N 个线段。不要忘记第 N 幢房子和第 1 幢房子也可以构成一个线段。这样,我们知道最短的距离其实就是少走了这 N 个线段中的最长距离。也就是湖的周长减去这 N 个线段中的最长距离。

不是很理解。没关系,我们使用样例数据 1 作为例子,进行详细过程分析。从样例输入 1 中,我们知道,湖周长为 20,第 1 幢房子的距离为 5,第 2 幢房子的距离为 10,第 3 幢房子的距离为 15。这样我们绘制出下图的房子分布。

那么我们就知道第一幢房子和第二幢房子之间的距离为 10 - 5 = 5,如下图红色线段所示。

第二幢房子和第三幢房子之间的距离为 15 - 10 = 5,如下图绿色线段所示。

第三幢房子和第一幢房子之间的距离为 20+5 - 15 = 10,如下图紫色线段所示。

上面的数据,我们不难看出以下几个结论:

1、所有房子之间的总距离就是湖泊的周长,5+5+10=20。

2、商人要访问这三个房子最短距离就是 5+5=10。也就是从第一幢出发,经过第二幢,到达第三幢。是不是最长的距离 10 没有走,走了其他距离。那么是不是就是湖的周长减去最大距离,20-10=10。

算法设计

经过上面的样例数据分析,我们就可以非常容易的设计出算法。算法的核心就是计算出最大的线段距离。算法过程就不写了,本题过于简单。是不是发现,有点像差分的模板题,就是多了一个记录差分的最大值。

AC 参考代码

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 2e5+4;
int a[MAXN];

int main() {
    int k,n;
    cin>>k>>n;

    int maxx = 0;
    cin>>a[0];
    for (int i=1; i<n; i++) {
        cin>>a[i];
        maxx = max(maxx, a[i]-a[i-1]);
    }
    maxx = max(maxx, k+a[0]-a[n-1]);

    cout << k - maxx << endl;

    return 0;
}

代码细节

第 N 幢房子和第 1 幢房子之间的距离,我们要注意是 k-a[n-1]+a[0]。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值