ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준-1963]-[BFS]-소수경로
    알고리즘/BFS_DFS 2018. 11. 23. 01:04

    문제 경로 : https://www.acmicpc.net/problem/1963




    이 문제는 까먹었던 소수에대해서 다시 기억하게 해준 고마운 문제다. 


    먼저 소수는 1 과 자신 이외에 나누어지지 않는 수를 소수라고 한다. 


    그럼 소수인지 아닌지 어떻게 확인할까??


    N이라는 수가 있다면 2부터 N 전의 정수로 전부 나눠서 하나라도 나누어지는 값이 있다면 그것은 소수가 아니고 나누어지는 값이 없다면 그 값은 소수이다. 


    1은 소수가 아니다. 


    그래서 1은 예외처리를 해줘야 한다. 



    소수 판별하는 소스


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        public static boolean isPrimeNum (int num) {
            boolean result = true;
            
            if(num == 1return false;
            
            for(int i = 2; i < num; i++) {
                if(num%i == 0) {
                    result = false;
                    break;
                }
            }
            return result;
        }
    cs


    이문제를 어떻게 접근할까 하다가 주어지는 수는 1000에서 9999까지의 네자리 수 실수가 주어진다고 한다. 

    그럼 1000 부터 9999까지 실수를 먼저 구해놓으면 나중에 시간이 덜 들 수 있어 보인다. 


    그리고 입력 받은 시작 값에서 목표 값까지 가기위해 BFS로 실수 인것들의 수를 세어 보았다. 


    BFS 소스 

    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
        public static void bfs(int startNum, int endNum) {
            int count = -1;
            boolean[] visited = new boolean[10000];
     
            Queue<int[]> queue = new LinkedList<int[]>();
            queue.offer(new int[]{startNum, 0});
            
            while(!queue.isEmpty()) {
                int num = queue.peek()[0];
                int cnt = queue.peek()[1];
                queue.poll();
                if(num == endNum) {
                    if(count == -1 || count > cnt) count = cnt;
                    continue;
                }
                if(num < 1000 || visited[num]) continue;
                
                visited[num] = true;
                
                for(int i=1; i <= 4; i++) {
                    for(int j = 0; j < 10; j++) {
                        int tNum = changeNum(num, i, j);
                        if(tNum >= 1000 && prime[tNum]) {
                            queue.offer(new int[] {tNum, cnt+1});
                        }
                    }
                }
            }
            
            if(count == -1System.out.println("Impossible");
            else System.out.println(count);
        }
    cs


    나머지는 전형적인 BFS 이고 20 번째 줄이 이번 문제에 특징을 가지고 있는 부분이다. 


    이중포문으로 구성되어 있는데 바깥 for문은 1000 자리부터 1의 자리까지 의 타입을 1~4로 나타낸것이다.

    안쪽 for문은 특정 자리수의 0 ~ 9 까지 반복하면서 수를 변경하기위해 사용했다. 


    변경한 수가 소수이면 큐에 저장하고 계속 반복하면 된다. 


    나머지는 전체 소스를 보면서 이해하면 될거 같다.


    소스

    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.StringTokenizer;
     
    public class Main {
     
        public static boolean[] prime;
        
        public static int[][] primeArr;
        
        public static void main(String[] args) throws IOException{
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = null;
            
            int size = Integer.parseInt(br.readLine());
     
            prime= new boolean[10000];
            primeArr = new int[size][10000];
            
            for(int i = 1000; i < 10000; i++) {
                prime[i] = isPrimeNum(i);
            }
            
            for(int i = 0; i < size; i++) {
                st = new StringTokenizer(br.readLine());
                int startNum = Integer.parseInt(st.nextToken());
                int endNum = Integer.parseInt(st.nextToken());
                bfs(startNum, endNum);
            }
        }
        public static void bfs(int startNum, int endNum) {
            int count = -1;
            boolean[] visited = new boolean[10000];
     
            Queue<int[]> queue = new LinkedList<int[]>();
            queue.offer(new int[]{startNum, 0});
            
            while(!queue.isEmpty()) {
                int num = queue.peek()[0];
                int cnt = queue.peek()[1];
                queue.poll();
                if(num == endNum) {
                    if(count == -1 || count > cnt) count = cnt;
                    continue;
                }
                if(num < 1000 || visited[num]) continue;
                
                visited[num] = true;
                
                for(int i=1; i <= 4; i++) {
                    for(int j = 0; j < 10; j++) {
                        int tNum = changeNum(num, i, j);
                        if(tNum >= 1000 && prime[tNum]) {
                            queue.offer(new int[] {tNum, cnt+1});
                        }
                    }
                }
            }
            
            if(count == -1System.out.println("Impossible");
            else System.out.println(count);
        }
        
        public static int changeNum(int num, int type, int t) {
            int resultNum = 0;
            switch(type) {
            case 1:    // 1000 의 자리
                resultNum = t * 1000;
                resultNum += (num - num/1000*1000);
                break;
            case 2:    // 100 의 자리
                resultNum = t * 100;
                resultNum += (num / 1000 * 1000+ (num - num / 100 * 100);
                break;
            case 3:    // 10의 자리
                resultNum = t * 10;
                resultNum += num/100*100 + (num - num / 10*10);
                break;
            case 4:    // 1 의 자리
                resultNum = t;
                resultNum += num / 10 * 10;
                break;
            }
            return resultNum;
        }
        public static boolean isPrimeNum (int num) {
            boolean result = true;
            
            if(num == 1return false;
            
            for(int i = 2; i < num; i++) {
                if(num%i == 0) {
                    result = false;
                    break;
                }
            }
            return result;
        }
    }
     
    cs


    '알고리즘 > BFS_DFS' 카테고리의 다른 글

    [백준-2668]-[DFS]-숫자고르기  (0) 2018.11.23
    [백준-1726]-[BFS]-로봇  (0) 2018.11.23
    [백준-2573]-[DFS-BFS]-빙산  (0) 2018.11.21
    [백준-2667]-[BFS]-단지번호 붙이기  (0) 2018.11.20
    [백준-2606]-[BFS]-바이러스  (0) 2018.11.20

    댓글

Designed by Tistory.