코테/코드트리

[코드트리/NOVICE MID] 4가지 연산을 이용하여 1 만들기 (JAVA)

imname1am 2024. 2. 5. 13:15
반응형

📖 문제

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

 

 

 

💡  풀이 방식

• 다익스트라 (397ms, 29MB)

연산횟수를 저장하는 1차원 int형 배열을 생성해 초기값을 큰 값으로 저장해두고, 시작점 N은 거리를 0으로 설정한다.

 

연산횟수가 적은 순으로 오름차순 정렬하는 우선순위 큐에 4가지 경우(현재 숫자에서 1을 뺀 경우, 1을 더한 경우, 2로 나눠 떨어질 경우 2로 나눈 경우, 3으로 나눠 떨어질 경우 3으로 나눈 경우)를 추가한다. 그리고 이동했을 때의 연산횟수와 현재 위치에서 1초 지난 값을 비교해  연산횟수 배열을 둘 중 더 값이 작은 값으로 갱신한다.

 

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.util.*;
import java.io.*;
 
public class Main {
    static final int MAX = 1_000_000;
 
    static int N;
    static int[] cntArr = new int[MAX + 1];
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
 
        Arrays.fill(cntArr, MAX);
 
        bfs();
        System.out.println(cntArr[1]);
    }
 
    private static void bfs() {
        cntArr[N] = 0;
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(N, 0));
 
        while(!pq.isEmpty()) {
            Node cur = pq.poll();
 
            int n1 = cur.num - 1;
            if(inRange(n1) && cntArr[n1] > cur.cnt + 1) {
                cntArr[n1] = cur.cnt + 1;
                pq.add(new Node(n1, cntArr[n1]));
            }
            
            int n2 = cur.num + 1;
            if(inRange(n2) && cntArr[n2] > cur.cnt + 1) {
                cntArr[n2] = cur.cnt + 1;
                pq.add(new Node(n2, cntArr[n2]));
            }
 
            if(cur.num % 2 == 0) {
                int n3 = cur.num / 2;
                if(inRange(n3) && cntArr[n3] > cur.cnt + 1) {
                    cntArr[n3] = cur.cnt + 1;
                    pq.add(new Node(n3, cntArr[n3]));
                }
            }
            
            if(cur.num % 3 == 0) {
                int n4 = cur.num / 3;
                if(inRange(n4) && cntArr[n4] > cur.cnt + 1) {
                    cntArr[n4] = cur.cnt + 1;
                    pq.add(new Node(n4, cntArr[n4]));
                }
            }         
        }
    }
 
    private static boolean inRange(int num) {
        return (1 <= num && num <= MAX);
    }
}
 
class Node implements Comparable<Node> {
    int num, cnt;
 
    public Node(int num, int cnt) {
        this.num = num;
        this.cnt = cnt;
    }
 
    @Override
    public int compareTo(Node n) {
        return this.cnt - n.cnt;
    }
}
cs

 

 

➕ 다른 풀이 방식

단순 BFS로도 풀 수 있다. (117ms, 9MB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.*;
import java.io.*;
 
public class Main {
    static final int MAX = 1_000_000;
    
    static int n;
    static boolean[] visited = new boolean[MAX + 1];
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        
        System.out.print(bfs());
    }
    static int bfs(){
        int ans = 0;
 
        Queue<int[]> q = new ArrayDeque<>();
        q.add(new int[]{n, 0});
 
        visited[n] = true;
        
        while(!q.isEmpty()){
            int[] now = q.poll();
            int val = now[0];
            int cnt = now[1];
            
            if(val == 1){
                ans = cnt;
                break;
            }
            
            if(inRange(val - 1&& !visited[val - 1]){
                visited[val-1= true;
                q.add(new int[]{val - 1, cnt + 1});
            }
            
            if(inRange(val + 1&& !visited[val + 1]){
                visited[val + 1= true;
                q.add(new int[]{val + 1, cnt + 1});
            }
            
            if(inRange(val) && val % 2 == 0 && !visited[val / 2]){
                visited[val / 2= true;
                q.add(new int[]{val / 2, cnt + 1});
            }
            
            if(inRange(val) && val % 3 == 0 && !visited[val/3]){
                visited[val / 3= true;
                q.add(new int[]{val / 3, cnt + 1});
            }
        }
        
        return ans;
    }
    
    private static boolean inRange(int num) {
        return (1 <= num && num <= MAX);
    }
}
cs


💦 어려웠던 점

X. 며칠 전 백준 숨바꼭질 3 문제랑 비슷해서 쉽게 풀 수 있었다.

 

 

🧐 새로 알게 된 내용

최소 연산 횟수 계산 = 각 연산의 가중치는 1이므로 가중치가 전부 1인 그래프가 있을 때 정점 n~1까지의 최단거리 계산 문제 ▷ BFS로 해결 가능

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

✔ 비슷한 문제 : 백준 13549 숨바꼭질3

 

[백준/JAVA] 13549번: 숨바꼭질 3

🔺 문제 13549번: 숨바꼭질 3 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만

bono039.tistory.com

 

반응형