ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 16197 - 두 동전
    Baekjoon 2022. 5. 28. 10:15

    생각했던 것

    문제의 모양을 보고 바로 BFS 문제라고 생각했다. 다만, 생각없이 visited 처리를 넣는 바람에 시간이 많이 걸렸다.
    문제의 키 포인트는 "벽에대한 처리"와, xor를 이용한 "동전이 하나만 떨어졌을 때의 감지"이다.

    추가적으로, 최소해를 찾기 위해서는 각 순회마다 따로 count를 세어줘야한다. (재귀를 사용한다면, 메소드의 파라미터에 count를 넘겨주므로 신경쓰지 않아도 됨)

    나는 bfs를 반복문으로 구현했기 때문에, 각 순회마다 따로 count를 세어주었다.

    ++ 예전에 풀었던 7576 - 토마토 문제에서는, count를 기록해주는 배열을 따로 만들어두었다. 해당 문제에서는 벽이 없었기 때문에, 해당 방식으로 저장 할 수 있었던것 같다.

    실수

    4방향 BFS에서 visited는 당연히 필요없다. visited가 있다면, 다음 순회로 넘어갈 때 이미 이전 순회에서 true를 4개나 만들어 두었으므로, 다음 순회를 정상적으로 진행 할 수 없게 된다.

    아쉬운 점

    코드에서 볼 수 있듯이, 동전이 2개이므로 순회마다 동전 2개의 위치를 저장한다. 해당 구현 방식에서 순회 횟수인 count를 두 동전에 모두 저장하는데, 실제로 사용하는 값은 두 개 중 하나만 사용한다. 같은 클래스를 사용하다보니 이렇게 되었는데.. 더 최적화 할 방법이 있을지도?

    내 코드의 장점

    해당 문제에서 원하는 답의 경우는 "두 개의 동전 중 하나의 동전만 떨어졌을 때"인데, 각각의 동전이 떨어진 상태를 boolean 변수에 넣어두고 xor 연산을 이용해 하나만 떨어졌을 때를 감지했다. 가독성도, 효율성도 이 방식이 가장 좋은듯하다.

    package backjoon;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.StringTokenizer;
    
    class P_16197{
        static class Cord {
            int x;
            int y;
            int count;
            Cord(int x, int y, int count) {
                this.x = x;
                this.y = y;
                this.count = count;
            }
        }
    
        static int[] dx = {1, -1, 0, 0};
        static int[] dy = {0, 0, 1, -1};
        static String[][] map;
    
        public static int bfs(ArrayList<Cord> coins) {
            Queue<Cord> fir = new LinkedList<>();
            Queue<Cord> sec = new LinkedList<>();
            fir.add(coins.get(0));
            sec.add(coins.get(1));
            while (!fir.isEmpty() && !sec.isEmpty())
            { // 남 북 동 서
                Cord first = fir.poll();
                Cord second = sec.poll();
                int fx = first.x;
                int fy = first.y;
                int sx = second.x;
                int sy = second.y;
                if (first.count >= 10) break;
                for (int i = 0; i < 4; i++) {
                    int fnx = fx + dx[i];
                    int fny = fy + dy[i];
                    int snx = sx + dx[i];
                    int sny = sy + dy[i];
                    boolean in_f = (fnx >= 0 && fnx < map.length && fny >= 0 && fny < map[0].length);
                    boolean in_s = (snx >= 0 && snx < map.length && sny >= 0 && sny < map[0].length);
                    if (in_f ^ in_s) return (first.count + 1);
                    else { // 0 0, 1 1
                        if (in_f) // 1 1
                        {
                            if (map[fnx][fny].equals("#") && !map[snx][sny].equals("#")) {
                                fir.add(new Cord(fx, fy, first.count + 1));
                                sec.add(new Cord(snx, sny, second.count + 1));
                            } else if (!map[fnx][fny].equals("#") && map[snx][sny].equals("#")) {
                                sec.add(new Cord(sx, sy, first.count + 1));
                                fir.add(new Cord(fnx, fny, second.count + 1));
                            } else if (!map[fnx][fny].equals("#") && !map[snx][sny].equals("#")) {
                                fir.add(new Cord(fnx, fny, first.count + 1));
                                sec.add(new Cord(snx, sny, second.count + 1));
                            }
                        }
                    }
                }
            }
            return (-1);
        }
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            int M = Integer.parseInt(st.nextToken());
            map = new String[N][M];
            ArrayList<Cord> coins = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                String[] elem = br.readLine().split("");
                for (int j = 0; j < M; j++) {
                    map[i][j] = elem[j];
                    if (map[i][j].equals("o")) coins.add(new Cord(i, j, 0));
                }
            }
            System.out.println(bfs(coins));
        }
    }

    'Baekjoon' 카테고리의 다른 글

    1074 - Z  (0) 2022.12.07
    2580 - 스도쿠  (0) 2022.05.30
    14888, 15685 - 연산자 끼워넣기 (1), (2)  (0) 2022.05.26
    20055 - 컨베이어 벨트 위의 로봇  (0) 2022.05.24
    1261 - 알고 스팟  (0) 2022.04.22
Designed by Tistory.