알고리즘/문제풀이
[BOJ] 15903 카드 합체 놀이 (Java)
세동세
2024. 10. 16. 20:24
문제 링크
https://www.acmicpc.net/problem/15903
문제 풀이
- x번 카드와 y번 카드를 골라 그 두 장에 쓰여진 수를 더한 값을 계산한다. (x ≠ y)
- 계산한 값을 x번 카드와 y번 카드 두 장 모두에 덮어 쓴다.
다음 조건을 만족해야한다.
최소 값을 두 장 더하고 이 값으로 갱신해주고, 다시 최소 값 2장을 2장으로 갱신한다는 것을 파악하자마자
우선순위큐를 활용하는 문제라고 생각했다.
일단, sort 가 반복문마다 적용되야 하는 조건이였고, 이는 최소 힙으로 맨 앞 2값씩 뽑으면 최소 값을 빠르게 갱신할 것 이라고 생각했다.
그래서 PQ로 금방 접근했지만, 틀렸습니다가 나와서 당황 ㅎㅎ
카드의 개수 n (2<= n<=1000)이므로 1000장의 카드가 있을 수 있다.
카드에 쓰여진 자연수 (1<=ai<=1,000,000) : 카드는 최대 백만이 쓰일 수 있다.
카드 합체 시 m(0<=m<=15 * n)이므로 15 * 1000번 합체할 수 있다.
모든 카드의 최대 값인 1,000,000이 쓰여있다고 쳤을 때, 2번 합체하면 2,000,000으로 증가하고,
이런 값이 15000번 이상 반복되면 21억은 충분히 뛰어넘을 수 있다.
int 형에서 오버플로가 발생할 수 있으니 Long 타입이 필요하다!
시험 문제에서 만났으면 맞왜틀??하면서 당황했을 것 같다ㅎㅎ
코드
package BOJ;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
/**
* BOJ_15903_카드합체놀이
*
* 아기 : 자연수 n장
* x번 카드 y 번 카드 골라 두 더한값
* x번 카드와 y번 카드에 모두 덮어씀
* m번 하면 끝남
* */
public class BOJ_15903_카드합체놀이 {
static BufferedReader br;
static StringTokenizer st;
public static void main(String[] args) throws IOException {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StringTokenizer(br.readLine().trim());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
PriorityQueue<Long> queue = new PriorityQueue();
st = new StringTokenizer(br.readLine().trim());
for (int idx = 0; idx < N; idx ++) {
queue.add(Long.parseLong(st.nextToken()));
}
for (int idx = 0; idx < M; idx ++) {
long a = queue.poll();
long b = queue.poll();
long tmp = a + b;
queue.add(tmp);
queue.add(tmp);
}
long result = 0;
while(!queue.isEmpty()) {
result += queue.poll();
}
System.out.println(result);
}
}