Post

BOJ 1461 도서관

BOJ 1461 도서관

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

문제

세준이는 도서관에서 일한다. 도서관의 개방시간이 끝나서 세준이는 사람들이 마구 놓은 책을 다시 가져다 놓아야 한다. 세준이는 현재 0에 있고, 사람들이 마구 놓은 책도 전부 0에 있다. 각 책들의 원래 위치가 주어질 때, 책을 모두 제자리에 놔둘 때 드는 최소 걸음 수를 계산하는 프로그램을 작성하시오. 세준이는 한 걸음에 좌표 1칸씩 가며, 책의 원래 위치는 정수 좌표이다. 책을 모두 제자리에 놔둔 후에는 다시 0으로 돌아올 필요는 없다. 그리고 세준이는 한 번에 최대 M권의 책을 들 수 있다.


입력

첫째 줄에 책의 개수 N과, 세준이가 한 번에 들 수 있는 책의 개수 M이 주어진다. 둘째 줄에는 책의 위치가 주어진다. N과 M은 50보다 작거나 같은 자연수이다. 책의 위치는 0이 아니며, 절댓값은 10,000보다 작거나 같은 정수이다.


출력

첫째 줄에 정답을 출력한다.


예제 입력 1

7 2
-37 2 -6 -39 -29 11 -28

예제 출력 1

131

예제 입력 2

8 3
-18 -9 -4 50 22 -26 40 -45

예제 출력 2

158

… 이하 예제 생략


코드

처음 볼 때는 간단하다고 생각했는데, 구현할 때 코드가 조금 더러워져서 은근히 시간이 많이 걸린 문제였다.

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {

    static int N;
    static int M;
    static PriorityQueue<Integer> leftBooks = new PriorityQueue<>();
    static PriorityQueue<Integer> rightBooks = new PriorityQueue<>(Comparator.reverseOrder());

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < N; i++) {
            int book = Integer.parseInt(st.nextToken());
            if(book > 0) {
                rightBooks.offer(book);
            } else {
                leftBooks.offer(book);
            }
        }

        int answer = calculateMinDistance();
        System.out.println(answer);
    }

    static int calculateMinDistance() {
        int movedDistance = 0;

        /**
         * 책을 제자리에 놔둔 후 다시 0으로 돌아올 필요가 없기 때문에
         * 가장 먼 거리에 있는 책을 놔두고 0으로 돌아오는 거리를 미리 차감하기 위해
         * 가장 왼쪽, 오른쪽에 있는 책 중 더 먼 거리를 미리 뺀다.
         */
        if(leftBooks.isEmpty() || !rightBooks.isEmpty() && Math.abs(leftBooks.peek()) < rightBooks.peek()) {
            movedDistance -= rightBooks.peek();
        } else {
            movedDistance -= Math.abs(leftBooks.peek());
        }

        // 왼쪽과 오른쪽에 있는 책을 놔두고 0으로 돌아오는 거리를 추가
        movedDistance += calculateMovedDistance(leftBooks);
        movedDistance += calculateMovedDistance(rightBooks);

        return movedDistance;
    }

    static int calculateMovedDistance(PriorityQueue<Integer> books) {
        int movedDistance = 0;

        while (!books.isEmpty()) {
            movedDistance += books.poll() * 2;
            for (int i = 1; i < M; i++) {
                books.poll();
            }
        }

        return Math.abs(movedDistance);
    }
}
This post is licensed under CC BY 4.0 by the author.