본문 바로가기
알고리즘/완전탐색

[java 백준]골드 4/ 1963번 소수경로

by Meaning_ 2022. 2. 26.
728x90
반응형

https://www.acmicpc.net/problem/1963

 

1963번: 소수 경로

소수를 유난히도 좋아하는 창영이는 게임 아이디 비밀번호를 4자리 ‘소수’로 정해놓았다. 어느 날 창영이는 친한 친구와 대화를 나누었는데: “이제 슬슬 비번 바꿀 때도 됐잖아” “응 지금

www.acmicpc.net

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.StringTokenizer;
 
public class Main {
 
    public static int n, first, last;
 
    public static boolean[] prime = new boolean[10000];
 
    public static int div[] = { 1000100101 };
 
    public static int BFS(int n) {
        int cnt = -1;
 
        Queue<Integer> queue = new LinkedList<Integer>();
        boolean[] visited = new boolean[10000];// visited도 초기화
 
        queue.add(n);
        visited[n] = true;
        while (!queue.isEmpty()) {
 
            cnt++;
 
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int node = queue.poll();
                if (node == last) {
 
                    return cnt;
                }
                int[] arr = new int[4];
                for (int j = 0; j < 4; j++) {
                    arr[j] = node / div[j];
                    node %= div[j];
                }
 
                for (int j = 0; j < 4; j++) {
                    for (int k = 0; k < 10; k++) {
                        if (arr[j] + 1 > 9) {
                            arr[j] = 0;
                        } else {
                            arr[j]++;
                        }
                        int num = 0;
                        for (int l = 0; l < 4; l++) {
                            num += arr[l] * div[l];
                        }
 
                        if (num >= 1000 && !visited[num] && !prime[num]) {
 
                            queue.add(num);
                            visited[num] = true;
                        }
                    }
 
                }
 
            }
 
        }
 
        return -1;
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        Scanner sc = new Scanner(System.in);
        n = Integer.parseInt(br.readLine());
 
        prime[0= prime[1= true;
 
        for (int i = 2; i < 10000; i++) {
            if (!prime[i]) {// 만약 prime[i]가 소수라면
                for (int j = 2; j * i < 10000; j++) {
                    prime[j * i] = true;
                }
            }
        }
 
        for (int k = 0; k < n; k++) {
            st = new StringTokenizer(br.readLine());
            first = Integer.parseInt(st.nextToken());
            last = Integer.parseInt(st.nextToken());
 
            int ans = BFS(first);
            if (ans != -1) {
                System.out.println(ans);
 
            } else {
                System.out.println("Impossible");
            }
 
        }
 
    }
 
}
cs

 

우선 소수판별을 에라토스테네스의 체를 사용하고 -> BFS탐색해주면서 첫번째 자리만 바꿨을때/두번째 자리만 바꿨을 때/세번째 자리만 바꿨을 때/네번째 자리만 바꿨을 때 소수일 경우 큐에 넣어준다 는 것 까진 생각해냈는데 어찌된건지 중간에 스텝이 꼬여서 춤추는 개발자님의 코드를 참고했다.

아래는 내가 스텝이 꼬인이유를 적어봤다.

 

1.자리수 분할할때 string이 아닌 int형으로만 분할해주기 (시간초과 예방)

만약에 1033이 들어오면 arr[0]은 1이 들어가고 나머지 애들인 33은 1033%1000의 결과이기에 node가 33으로 바뀌는 식이다.

나는 string배열로 바꿔서 문제를 풀었는데 이러니까 코드가 너무 길어지고 시간초과에 걸릴 위험이 컸다. 

 

 

2. 어떤게 queue에 들어와도 결국 최종 cnt(개수)는 같다!

 

1033을 한번 탐색하고 나면 큐에는 1433,1733,1933 등등의 숫자가 들어온다. 나는 발문에서 1033이후에 바로 1733이 나와서 1733이 아니면 답이 달리지는 줄 알았다. 근데 1433,1733,1933 등 그 회차에 첫번째 자리부터 네번째자리 까지 하나씩만 바꿨을 때 소수로 판별된 애들을 BFS돌려주면 결국 최종 cnt는 다 똑같았다! 

 

3.(중요!) visited는 BFS메서드가 새로 시작할때마다 초기화 해줘야 한다!

 

너무 당연하지만 항상 이런데서 놓친다..ㅋㅋ

 

참고 사이트 

https://log-laboratory.tistory.com/113

 

[백준] 1963번 자바 소수 경로

문제 출처 https://www.acmicpc.net/problem/1963 1963번: 소수 경로 문제 소수를 유난히도 좋아하는 창영이는 게임 아이디 비밀번호를 4자리 ‘소수’로 정해놓았다. 어느 날 창영이는 친한 친구와 대화를

log-laboratory.tistory.com

 

728x90
반응형

댓글