코딩테스트
백준 1463번 1로 만들기(java) - 다이나믹 프로그래밍, bfs
leeeehhjj
2021. 6. 1. 15:25
정수 N 이 0일 때와 1일 때 연산 횟수는 0회이므로
dp[0] = dp[1] = 0
이고 N = 2 일 때부터는 N에 -1했을 때, / 3 했을 때, / 2 했을 때를 모두 실행하여 가장 작은 값을 dp[n]에 넣어주면 된다. 즉, dp[n] = dp[n-1] + 1 or dp[n / 3] +1 or dp[n / 2] + 1이다. 이 때 1을 더해주는 이유는 -1 이나 / 3 이나 /2 연산을 한 번 실행했기 때문이다.
import java.util.Scanner;
public class Test {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 0;
for(int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + 1;
if(i % 3 == 0) {
dp[i] = Math.min(dp[i], dp[i / 3] + 1);
}
if(i % 2 == 0) {
dp[i] = Math.min(dp[i], dp[i / 2] + 1);
}
}
System.out.println(dp[n]);
scanner.close();
}
}
+ ) 풀이 추가 - bfs
bfs를 활용해서 n에 대해 2로 나누기, 3으로 나누기, -1 빼기를 모두 수행해서 queue에 넣는다.
bfs 수행 후 수가 1이 되면 연산 횟수를 출력한다(bfs 이므로 가장 먼저 1이 되는 경우가 가장 최소의 연산 횟수를 갖는 경우이다)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
class Info {
int num;
int cnt;
Info (int num, int cnt) {
this.num = num;
this.cnt = cnt;
}
}
public class Main {
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
boolean[] visited = new boolean[n+1];
Queue<Info> que = new LinkedList<>();
que.offer(new Info(n, 0));
visited[n] = true;
while (!que.isEmpty()) {
Info now = que.poll();
if (now.num == 1) {
System.out.println(now.cnt);
System.exit(0);
}
if (now.num % 3 == 0 && !visited[now.num / 3]) {
visited[now.num / 3] = true;
que.offer(new Info(now.num/3, now.cnt+1));
}
if (now.num % 2 == 0 && !visited[now.num / 2]) {
visited[now.num/2] = true;
que.offer(new Info(now.num / 2, now.cnt+1));
}
if (!visited[now.num - 1]) {
visited[now.num - 1] = true;
que.offer(new Info(now.num - 1, now.cnt+1));
}
}
}
}