알고리즘/구현

[BOJ] 백준 10655 - 마라톤 1 풀이

송승현(SSH) 2023. 1. 11. 00:14

1. 문제

https://www.acmicpc.net/problem/10655

 

10655번: 마라톤 1

젖소 박승원은 2번째 혹은 3번째 체크포인트를 건너뛸 수 있는데, 여기서 두 번째 체크포인트를 건너뛸 경우 경로는 (0,0) -> (11,-1) -> (10,0) 이 되며 거리는 14이다. 박승원은 이것보다 더 짧게 달릴

www.acmicpc.net

 

2. 풀이

백준 실버 3에 해당하는 문제이다. 생각보다 쉬운 문제를 삽질을 너무 많이 한 문제이다. 

1. 첫 번째 삽질
처음 문제를 풀 때 "모든 체크 포인트를 순서대로 방문한 후"를 못 보고 모든 체크 포인트를 방문했을 때 가장 최소로 걸리는 길을 찾는 문제로 봐서 다익스트라로 해결하려 했다. (문제를 제대로 좀 읽자... 제발...)

2. 브루트포스 확인
건너뛰려는 포인트를 하나씩 잡고 그때마다 이중 반복문을 돌려 거리를 구했다. 정답은 나왔지만, 최악의 경우 100,000 * 99,999번을 탐색해야 하므로 시간 초과가 났다.

3. 정답
우선 모든 체크 포인트를 순서대로 방문했을 때 이동 거리를 구한 후, 건너 뛸 체크 포인트를 하나씩 탐색한 후 작업을 진행했다.
예를 들어 i번 째 체크 포인트를 건너 뛴다고 했을 때, (i, i - 1) - (i, i + 1) + (i -1, i + 1)을 해주면 i번 째 체크 포인트를 건너 뛴 거리가 나오게 된다. 이를 아까 구한 전체 거리에서 빼준다면 i번 째 체크 포인트를 건너 뛴 총 이동 거리가 나온다.


3. 소스코드

1. 브루트포스 확인 코드(시간 초과)

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
    static class Point {
        int x;
        int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static List<Point> pointList = new ArrayList<>();
    static int pointCnt;
    static Point oldPoint;

    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        pointCnt = Integer.parseInt(br.readLine());
        for (int i = 0; i < pointCnt; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            pointList.add(new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())));
        }

        int result = Integer.MAX_VALUE;
        for (int i = 1; i < pointCnt - 1; i++) {
            int sum = 0;
            int[] visited = new int[pointCnt];
            visited[i] = 2;

            oldPoint = pointList.get(0);
            visited[0] = 1;

            for (int j = 1; j < pointCnt; j++) {
                if (j == i || visited[j] == 1) {
                    continue;
                } else {
                    sum += distanceHap(j);
                    oldPoint = pointList.get(j);
                    visited[j] = 1;
                }
            }

            result = Math.min(result, sum);
        }

        bw.write(Integer.toString(result) + "\n");
        bw.flush();
        bw.close();
        br.close();
    }

    static int distanceHap(int idx) {
        return Math.abs(pointList.get(idx).x - oldPoint.x) + Math.abs(pointList.get(idx).y - oldPoint.y);
    }
}


2. 정답 코드

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
    static class Point {
        int x;
        int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    static List<Point> pointList = new ArrayList<>();
    static int pointCnt;

    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        pointCnt = Integer.parseInt(br.readLine());
        for (int i = 0; i < pointCnt; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            pointList.add(new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())));
        }

        int sum = 0;
        for (int i = 0; i < pointCnt - 1; i++) {
            sum += distanceHap(i, i + 1);
        }

        int result = sum;
        for (int i = 1; i < pointCnt - 1; i++) {
            int loopSum = sum - (distanceHap(i, i + 1) + distanceHap(i, i - 1)) + distanceHap(i - 1, i + 1);

            result = Math.min(loopSum, result);
        }

        bw.write(Integer.toString(result) + "\n");
        bw.flush();
        bw.close();
        br.close();
    }

    static int distanceHap(int first, int second) {
        return Math.abs(pointList.get(first).x - pointList.get(second).x) + Math.abs(pointList.get(first).y - pointList.get(second).y);
    }
}