문제
영선이는 매우 기쁘기 때문에, 효빈이에게 스마일 이모티콘을 S개 보내려고 한다.
영선이는 이미 화면에 이모티콘 1개를 입력했다. 이제, 다음과 같은 3가지 연산만 사용해서 이모티콘을 S개 만들어 보려고 한다.
- 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장한다.
- 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기 한다.
- 화면에 있는 이모티콘 중 하나를 삭제한다.
모든 연산은 1초가 걸린다. 또, 클립보드에 이모티콘을 복사하면 이전에 클립보드에 있던 내용은 덮어쓰기가 된다. 클립보드가 비어있는 상태에는 붙여넣기를 할 수 없으며, 일부만 클립보드에 복사할 수는 없다. 또한, 클립보드에 있는 이모티콘 중 일부를 삭제할 수 없다. 화면에 이모티콘을 붙여넣기 하면, 클립보드에 있는 이모티콘의 개수가 화면에 추가된다.
영선이가 S개의 이모티콘을 화면에 만드는데 걸리는 시간의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 S (2 ≤ S ≤ 1000) 가 주어진다.
출력
첫째 줄에 이모티콘을 S개 만들기 위해 필요한 시간의 최솟값을 출력한다.
예제 입력 1
2
예제 출력 1
2
예제 입력 2
4
예제 출력 2
4
예제 입력 3
6
예제 출력 3
5
예제 입력 4
18
예제 출력 4
8
소스코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
public class Main {
private static BufferedReader br;
private static int S;
static class State {
int viewCnt, clipCnt, time; // 화면의 이모티콘 개수, 클립보드의 이모티콘 개수, 현재까지 연산 시간
public State(int viewCnt, int clipCnt, int time) {
super();
this.viewCnt = viewCnt;
this.clipCnt = clipCnt;
this.time = time;
}
@Override
public String toString() {
return "State [viewCnt=" + viewCnt + ", clipCnt=" + clipCnt + ", time=" + time + "]";
}
}
public static void main(String[] args) throws NumberFormatException, IOException {
br=new BufferedReader(new InputStreamReader(System.in));
S=Integer.parseInt(br.readLine());
int result=bfs(); // S개의 이모티콘을 만드는데 걸리는 시간의 최솟값 계산
System.out.println(result);
}
private static int bfs() { // 너비 우선 탐색을 통해 각 State에 대해 1, 2, 3번을 수행했을 때 중 가장 먼저 S에 도달하는 경우를 구함
Queue<State> queue=new LinkedList<>(); // 큐에 초기 상태를 대입
queue.add(new State(1, 0, 0));
boolean [][]visited=new boolean[10001][10001]; // [화면의 이모티콘 개수][클립보드의 이모티콘 개수] 에 대해 방문 여부 체크
visited[1][0]=true;
while(!queue.isEmpty()) {
State state=queue.poll();
if(state.viewCnt==S) return state.time; // 화면에 S개의 이모티콘을 만든 경우 현재 시간을 리턴
if(state.viewCnt!=state.clipCnt && !visited[state.viewCnt][state.viewCnt]) { // 1. 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장
visited[state.viewCnt][state.viewCnt]=true;
queue.add(new State(state.viewCnt, state.viewCnt, state.time+1));
}
if(!visited[state.viewCnt+state.clipCnt][state.clipCnt]) { // 2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기
visited[state.viewCnt+state.clipCnt][state.clipCnt]=true;
queue.add(new State(state.viewCnt+state.clipCnt, state.clipCnt, state.time+1));
}
if(state.viewCnt-1>0 && !visited[state.viewCnt-1][state.clipCnt]) { // 3. 화면에 있는 이모티콘 중 하나를 삭제
visited[state.viewCnt-1][state.clipCnt]=true;
queue.add(new State(state.viewCnt-1, state.clipCnt, state.time+1));
}
}
return 0;
}
}
1. 현재 화면의 이모티콘 개수, 클립보드의 이모티콘 개수, 시간 을 관리할 State 클래스를 만듭니다.
2. 너비 우선 탐색을 통해 1,2,3번을 각각 탐색하며 화면에 S개의 이모티콘이 나타나는 최소 시간을 구합니다.
2-1. 화면에 있는 이모티콘을 모두 복사해서 클립보드에 저장
화면의 이모티콘 개수와 클립보드의 이모티콘 개수가 다르고 해당 요소를 방문하지 않은 경우, 방문 처리 후 큐에 넣 어줌
2-2. 클립보드에 있는 모든 이모티콘을 화면에 붙여넣기
클립보드의 이모티콘과 화면 이모티콘 개수를 더한 값을 화면 이모티콘에 대입했을 때 해당 요소를 방문하지 않은 경 우, 방문 처리 후 큐에 넣어줌
2-3. 화면에 있는 이모티콘 중 하나를 삭제
화면의 이모티콘 개수-1 이 0보다 크고 해당 요소를 방문하지 않은 경우, 방문 처리 후 큐에 넣어줌
'코딩테스트 > 다이나믹 프로그래밍(Dynamic Programming))' 카테고리의 다른 글
[Java] 백준 5557번 : 1학년 (0) | 2022.05.26 |
---|---|
[Java] 백준 2565번 : 전깃줄 (0) | 2022.05.24 |
[Java] 백준 16195번 : 1, 2, 3 더하기 9 (0) | 2022.05.21 |
[Java] 백준 15993번 : 1, 2, 3 더하기 8 (0) | 2022.05.21 |
[Java] 백준 15992번 : 1, 2, 3 더하기 7 (0) | 2022.05.20 |