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();
  }
}

댓글남기기