📙 Algorithm Solving/Java
📙[Algo] BOJ1461. 도서관
혜덕hyeduck
2024. 9. 25. 19:20
https://www.acmicpc.net/problem/1461
문제 요약
- 세준이는 현재 0에 위치
- 책들도 0에 위치
- 각 책들의 원래 위치가 주어질 때, 책을 모두 제자리에 둘 때 드는 최소 걸음수는?
- 마지막에 0으로 돌아올 필요 X
- 한 번에 최대 M권의 책을 들 수 있음
시간 제한
- 2초
입력
- 책의 개수 N과 한 번에 들 수 있는 책 개수 M
- N과 M은 50이하 자연수
- 책의 원래 위치가 주어진다.
- 0인 경우는 없으며, -10000~10000 범위 내 정수
출력
- 다 정리하는 데 필요한 최소 걸음 수 출력
접근법
- 테케1
- M = 2
- 책 원래 위치(정렬) : -1 0 3 4 5 6 11
- 4번, 5번 책 두고 오기 ⇒ 5 + 5 = 10
- -1번 책 두고 오기 ⇒ 1 + 1 = 2
- 3번 책 두고 오기 ⇒ 3 + 3 = 6
- 6번, 11번 책 두기 ⇒ 11
- 테케2
- M = 2
- 책 원래 위치(정렬) : -39 -37 -29 -28 -6 0 2 11
- 2번, 11번 책 두고오기 ⇒ 11 + 11 = 22
- -6번 책 두고 오기 ⇒ 6 + 6 = 12
- -29, -28 번 책 두고 오기 ⇒ 29 + 29 = 58
- -39, -37번 책 두기 ⇒ 39
- 테케3
- M = 3
- 책 원래 위치(정렬) : -45 -26 -18 -9 -4 0 22 40 50
- -9번, -4번 책 두고 오기 ⇒ 9 + 9 = 18
- -45 , -26, -18번 책 두고 오기 ⇒ 45 + 45 = 90
- 22, 40, 50번 책 두기 ⇒ 50
- 걸음수는 현재 들고 있는 책의 위치 중 절댓값의 최댓값에 영향 받음
- 들고있는 나머지 책들은 해당 책을 두러가는 길에 둔다. ⇒ 따라서 음수끼리, 양수끼리 들어야함
- 절댓값이 가장 최대인 책을 포함한 연속된 M권은 가장 마지막에 둘 것
- 나머지는
- 음수일 경우 가장 왼쪽에서 M개씩 묶어서 이동
- 양수일 경우 가장 오른쪽에서 M개씩 묶어서 이동
- 이때 양수구간 음수구간을 따로 나눠서 while문을 돌렸다
- 음수구간
- start포인터는 절대값이 최대인 값을 가리킨다.
- start와 end 포인터모두 0부터 시작 → 오른쪽 이동
- while문 조건 ⇒ end가 N미만 이고, start가 가리키는 원소가 음수인 경우
- end를 기준으로 M개가 될 때까지 최대한 오른쪽으로 이동
- start는 M개를 채웠을 때 end 다음 위치로 이동
- 양수구간
- end포인터는 절대값이 최대인 값을 가리킨다.
- start와 end포인터 모두 N-1부터 시작 → 왼쪽 이동
- while문 조건 ⇒ start가 0이상 이고, end가 가리키는 원소가 양수인 경우
- start를 기준으로 M개가 될 때까지 최대한 왼쪽으로 이동
- end는 M개가 채웠을 때 start 이전 위치로 이동
- 음수구간
코드
import java.io.*;
import java.util.*;
public class Main {
static int N, M;
static int[] pos;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
pos = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
pos[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(pos);
int max = Math.max(Math.abs(pos[0]), Math.abs(pos[N - 1])); // 가정 멀리있는 책 위치
int answer = 0, start = 0, end = 0;
// 음수 그룹
while (end < N && pos[start] < 0) {
// 책 두고 오기
if (pos[start] < 0 && pos[end] > 0) {
// 양수인 구간을 만났다면.
answer += Math.abs(pos[start]) * 2;
break;
} else if (end - start + 1 == M) {
// 개수 최대 M개를 채웠다면
answer += Math.abs(pos[start]) * 2;
start = end + 1;
} else if (end == N - 1) {
// 책의 마지막 구간을 만났다면
answer += Math.abs(pos[start]) * 2;
}
end++;
}
// 양수 그룹
start = N - 1; end = N - 1;
while ( 0 <= start && pos[end] > 0) {
// 책 두고 오기
if (pos[end] > 0 && pos[start] < 0) {
// 음수인 구간을 만났다면
answer += pos[end] * 2;
break;
} else if (end - start + 1 == M) {
// 개수 최대 M개를 채웠다면
answer += pos[end] * 2;
end = start - 1;
} else if (start == 0) {
// 책의 마지막 구간을 만났다면
answer += pos[end] * 2;
}
start--;
}
System.out.println(answer - max);
}
}