Algorithm
[Java] BaekJoon 14226. 이모티콘 (BFS) (골드5)
Per ardua ad astra !
2022. 1. 9. 18:01
문제출처: https://www.acmicpc.net/problem/14226
14226번: 이모티콘
영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다. 영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만
www.acmicpc.net
문제이해
목표
다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만들어 보려고 한다. (2 <= S <= 1000)
1. 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.
2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.
3. 화면에 있는 이모티콘 중 하나를 삭제한다.
모든 연산은 1초가 걸린다.
영선이가 S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성
풀이
DP 문제로 이해 => X 틀림
DP로만 풀게 되면 3번 조건(이모티콘 중 하나 삭제)으로 구할 수 있는 최소값 경우의 수를 고려하지 못함 or 고려하더라도 너무 많은 경우를 탐색해야되서 초과
=> DP와 BFS로 풀이 (탐색 우선 순위는 해당 이모티콘을 출력하기까지 Price(시간)가 낮은 순서대로)
min[]: 최소 걸리는 시간을 다루는 배열
인덱스: i개의 이모티콘,
값: i개의 이모티콘을 만드는데 걸리는 시간의 최솟값
1. 증식 방법
- 자기보다 1 적은 이모티콘으로 탐색 -> min[현재 - 1] + 1
- 자기 * j (j: 2~) 배수의 이모티콘으로 탐색 -> min[현재 * j] + j
2. 증식과 함께 갱신
증식: 큐에 넣어서 BFS 탐색을 한다.
갱신: 가능한 적은 price비용으로 min[]의 값을 갱신한다.
주의
min[]의 초기화: => min[i] = i
- 1을 복사에서 i번씩 복붙하는 경우가 시간의 최댓값 이므로 인덱스 값으로 초기화
- 의미: 위의 증식방법 2가지로 했을 때 도달하지 못할 수 있는 소수값을 미리 의미있는 최대값으로 초기화 시켜서 잘못된 정답이 도출될 수 있는 것을 방지
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
/*
낮은 cost(시간)로 먼저 BFS 탐색하는 알고리즘
증식 방법->
- 자기보다 1 적은 이모티콘으로 탐색 -> min[현재 - 1] + 1
- 자기 * j 배수의 이모티콘으로 탐색 -> min[현재 * j] + j
*/
public class 이모티콘 {
final static int PRICEMAX = 1000;
final static int INDEXMAX = 1010;
private static int[] min;
private static int N;
static class Emoticon {
int index;
int price;
public Emoticon(int index, int price) {
this.index = index;
this.price = price;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
// 최소 걸리는 시간을 다루는 배열(인덱스: i개의 이모티콘, 값: i개의 이모티콘을 만드는데 걸리는 시간의 최솟값)
min = new int[INDEXMAX];
for (int i = 1; i < INDEXMAX; i++) { // 1을 복사에서 i번씩 복붙할 수 있음으로 인데그 값으로 초기화
min[i] = i;
}
// BFS를 탐색할 PriorityQueue 생성
PriorityQueue<Emoticon> pq = new PriorityQueue<Emoticon>((a, b) -> {
return a.price - b.price;
});
pq.add(new Emoticon(2, 2));
pq.add(new Emoticon(3, 3));
// BFS
while (!pq.isEmpty()) {
Emoticon emoticon = pq.poll();
int index = emoticon.index;
int price = emoticon.price;
if (index == N) {
break;
}
if (index <= 0 || index >= INDEXMAX - 1 || price > min[index]) {
continue;
}
// 이모티콘 - 1 한 값에 접근
if (min[index - 1] >= price + 1) {
min[index - 1] = price + 1;
pq.add(new Emoticon(index - 1, min[index - 1]));
}
// 이모티콘 * j (배수) 값에 접근
for (int j = 2; j < INDEXMAX; j++) {
int multipleIndex = index * j; // 배수
if (multipleIndex >= INDEXMAX) {
break;
}
if (min[multipleIndex] >= price + j) {
min[multipleIndex] = price + j;
pq.add(new Emoticon(multipleIndex, min[multipleIndex]));
}
}
}
System.out.println(min[N]);
}
}