[백준 10655] 마라톤 1 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
N개의 체크포인트를 순서대로 이동할 때, 첫 번째와 마지막을 제외한 중간 체크포인트 하나를 건너뛸 수 있습니다. 맨해튼 거리로 측정했을 때 최소 총 이동 거리를 구하는 문제입니다.
접근법
먼저, 모든 체크포인트를 순서대로 방문했을 때의 총 거리를 계산합니다. 인접한 두 점 사이의 맨해튼 거리를 모두 더합니다.
다음으로, 각 중간 체크포인트를 건너뛰었을 때 절약되는 거리를 계산합니다. i번째 체크포인트를 건너뛰면 원래 거리에서 이전-현재-다음 구간의 거리를 빼고, 이전-다음 직접 이동 거리를 더합니다. 이 차이가 절약량이 됩니다.
이후, 모든 중간 체크포인트에 대해 절약량의 최댓값을 구하고, 총 거리에서 이 값을 빼면 최소 이동 거리가 됩니다.
시간 복잡도는 O(N)입니다.
Code
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Collections.Generic;
namespace Solution {
class Program {
static int Dist((int x, int y) a, (int x, int y) b) {
return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
}
static void Main(string[] args) {
var n = int.Parse(Console.ReadLine()!);
var pts = new List<(int x, int y)>(n);
for (var i = 0; i < n; i++) {
var s = Console.ReadLine()!.Split();
pts.Add((int.Parse(s[0]), int.Parse(s[1])));
}
var total = 0;
for (var i = 0; i < n - 1; i++)
total += Dist(pts[i], pts[i + 1]);
var bestSave = 0;
for (var i = 1; i < n - 1; i++) {
var d1 = Dist(pts[i - 1], pts[i]) + Dist(pts[i], pts[i + 1]);
var d2 = Dist(pts[i - 1], pts[i + 1]);
var save = d1 - d2;
if (save > bestSave)
bestSave = save;
}
Console.WriteLine(total - bestSave);
}
}
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef vector<pii> vp;
int dist(pii a, pii b) {
return abs(a.first - b.first) + abs(a.second - b.second);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
vp p(n);
for (int i = 0; i < n; i++)
cin >> p[i].first >> p[i].second;
int total = 0;
for (int i = 0; i < n - 1; i++)
total += dist(p[i], p[i + 1]);
int bestSave = 0;
for (int i = 1; i < n - 1; i++) {
int d1 = dist(p[i - 1], p[i]) + dist(p[i], p[i + 1]);
int d2 = dist(p[i - 1], p[i + 1]);
bestSave = max(bestSave, d1 - d2);
}
cout << total - bestSave << "\n";
return 0;
}