2 분 소요

1. 문제

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

// 예제 입력 3
6 2
3 4 5 6 11 -1

// 예제 출력 3
29

// 예제 입력 4
1 50
1

// 예제 출력 4
1


2. 핵심 아이디어

  • 일직선상의 각 책들을 원래의 위치에 놓아야 함
  • 0보다 큰 책들과 0보다 작은 책들을 나누어서 처리
  • 두 개의 우선순위 큐를 이용하여 문제를 효과적으로 해결할 수 있음
  • 마지막 책을 놓을 때는 다시 0으로 돌아올 필요가 없으므로, 가장 먼 책을 마지막으로 놓음


3. Python 문제풀이

import sys
import heapq

n, m = map(int, input().split(' '))
arr = list(map(int, input().split(' ')))
positive = []
negative = []

# 가장 거리가 먼 책까지의 거리
largest = max(max(arr), - min(arr))

# 최대 힙을 위해 원소를 음수로 구성
for i in arr :
  # 책의 위치가 양수인 경우
  if i > 0 :
    heapq.heappush(positive, -i)
  # 책의 위치가 음수인 경우
  else :
    heapq.heappush(negative, i)

result = 0

while positive :
  # 한 번에 m개씩 옮길 수 있으므로 m개씩 빼내기
  result += heapq.heappop(positive)
  for _ in range(m - 1) :
    if positive :
      heapq.heappop(positive)

while negative :
  # 한 번에 m개씩 옮길 수 있으므로 m개씩 빼내기
  result += heapq.heappop(negative)
  for _ in range(m - 1) :
    if negative :
      heapq.heappop(negative)

# 일반적으로 왕복 거리를 계산하지만, 가장 먼 곳은 편도 거리 계산
print(-result * 2 - largest)


4. Java 문제풀이

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    StringTokenizer st = new StringTokenizer(br.readLine());
    int n = Integer.parseInt(st.nextToken());
    int m = Integer.parseInt(st.nextToken());

    PriorityQueue<Integer> positive = new PriorityQueue<>((p1, p2) -> p2 - p1);
    PriorityQueue<Integer> negative = new PriorityQueue<>((p1, p2) -> p2 - p1);

    st = new StringTokenizer(br.readLine());
    for (int i=0; i<n; i++) {
      int temp = Integer.parseInt(st.nextToken());
      if (temp > 0) {
        positive.offer(temp);
      } else {
        negative.offer(Math.abs(temp));
      }
    }

    int largest = 0;
    if (positive.isEmpty()) {
      largest = negative.peek();
    } else if (negative.isEmpty()) {
      largest = positive.peek();
    } else {
      largest = Math.max(positive.peek(), negative.peek());
    }

    int ans = 0;

    while (!positive.isEmpty()) {
      int result = positive.poll();
      for (int i=0; i<m-1; i++) {
        positive.poll();
        if (positive.isEmpty()) {
          break;
        }
      }
      ans += result * 2;
    }

    while (!negative.isEmpty()) {
      int result = negative.poll();
      for (int i=0; i<m-1; i++) {
        negative.poll();
        if (negative.isEmpty()) {
          break;
        }
      }
      ans += result * 2;
    }

    ans -= largest;
    bw.write(ans + "\n");
    bw.flush();
    bw.close();
    br.close();
  }
}

댓글남기기