ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BOJ) 백조의 호수
    알고리즘/백준 2020. 6. 12. 23:29
    반응형

    백조의 호수

     

    3197번: 백조의 호수

    문제 두 마리의 백조가 호수에서 살고 있었다. 그렇지만 두 마리는 호수를 덮고 있는 빙판으로 만나지 못한다. 호수는 가로로 R, 세로로 C만큼의 직사각형 모양이다. 어떤 칸은 얼음으로 덮여있�

    www.acmicpc.net

     

    풀이

     

    처음 코테를 준비할 때 풀다가 실패한 문제였다. 그게 벌써 1년은 더 지난 것 같다.

    1년간 매일같이 코테 연습을 하지는 않았지만, 실력이 많이 늘었을 거란 생각에 다시 도전했다.

    하지만, 처참히 깨졌다... 

     

    처음으로 짰던 코드는, 가지치기 없이 BFS를 날마다 돌리면서 답을 찾는 것이었다.

    6%에서 시간초과가 떴고, 시간 초과를 회피할 오랫동안 생각하다가 떠오르지 않아서 여러 블로그를 참고했다.

    Union-Find로 문제를 해결한 분들도 계셨고, BFS와 BinarySearch를 이용해 푸신 분들도 계셨다.

     

    하지만, 두 코드 모두 유사한 문제에서 내가 접근할 수 있는 방법은 아닐 것 같다는 생각이 들었다.

    결국 BFS로만 문제를 푸는 방법을 찾다가, 내가 고민했던 흔적이랑 최대한 비슷한 글들을 참고했다.

     

    Visit 부분을 한번만 초기화하고 백조가 움직이는 LinkedList를 바꾸는 방법으로 코드를 수정했다.

    처음 백조를 시작으로, 매 회마다 백조에서 움직일 수 있는 위치를 담아가면서 날짜와 연관되게 설정했다.

     

    이 부분을 토대로 자잘한 부분들을 신경써주니까, 바로 통과가 되었다.

    사실, 이 로직도 스쳐지나갔던 여러 고민 중 하나였다.

    할까 말까 고민하기보다 우선 해보는 것도 나쁘지는 않은 것 같다.

     

    코드

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.LinkedList;
    
    public class SwanLake_3197 {
        final static char SWAN = 'L', ICE = 'X', WATER = '.';
        final static int[] dx = {0,1,0,-1}, dy = {1,0,-1,0};
        final static int directions = 4;
        static int visit[][];
        static LinkedList<WaterPos> swanList;
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String sizeStr = br.readLine();
            int y= Integer.parseInt(sizeStr.split(" ")[0]);
            char[][] map = new char[y][];
    
            for(int i=0; i<y; i++) {
                map[i] = br.readLine().toCharArray();
            }
    
            System.out.println(solution(map));
    
            br.close();
        }
    
        private static int solution(char[][] map) {
            int answer =0;
            int maxX = map[0].length;
            int maxY = map.length;
    
            visit = new int[maxY][maxX];
            LinkedList<WaterPos> waterList = new LinkedList<>();
            swanList = new LinkedList<>();
            WaterPos[] swans = new WaterPos[2];
    
            int idx=0;
            for(int y=0; y<maxY; y++) {
                for(int x=0; x<maxX; x++) {
                    if(map[y][x] ==WATER || map[y][x] == SWAN) {
                        WaterPos pos = new WaterPos(x,y);
                        waterList.offer(pos);
                        if(map[y][x] == SWAN) {
                            swans[idx++] = pos;
                        }
                    }
                }
            }
            swanList.offer(swans[0]);
            visit[swans[0].y][swans[0].x] =1;
    
            while(!isMeetSwans(swans,map)) {
                int size = waterList.size();
                for(int i=0; i<size; i++) {
                    WaterPos pos = waterList.poll();
                    for(int j=0; j<directions; j++) {
                        int ny = pos.y + dy[j];
                        int nx = pos.x + dx[j];
    
                        if(isInArea(nx,ny,maxX,maxY)) {
                            if(map[ny][nx] == ICE) {
                                map[ny][nx] = WATER;
                                waterList.offer(new WaterPos(nx,ny));
                            }
                        }
                    }
                }
                answer++;
            }
    
            return answer;
        }
    
        private static boolean isMeetSwans(WaterPos[] swans, char[][] map) {
            boolean result = false;
    
            LinkedList<WaterPos> moveList = new LinkedList<>();
            int maxX = map[0].length;
            int maxY = map.length;
    
            while(!swanList.isEmpty()) {
                WaterPos pos = swanList.poll();
                if(pos.x == swans[1].x && pos.y == swans[1].y) {
                    result = true;
                    break;
                }
                for(int i=0; i<directions; i++) {
                    int ny = pos.y + dy[i];
                    int nx = pos.x + dx[i];
                    if(isInArea(nx,ny,maxX,maxY)) {
                        if(visit[ny][nx] ==0) {
                            if(map[ny][nx] == ICE) {
                                moveList.offer(new WaterPos(nx,ny));
                            } else {
                                swanList.offer(new WaterPos(nx,ny));
                            }
                            visit[ny][nx] = 1;
                        }
                    }
                }
            }
    
            if(visit[swans[1].y][swans[1].x] ==1) {
                result = true;
            }
            swanList = moveList;
    
            return result;
        }
    
        private static boolean isInArea(int x, int y, int maxX, int maxY) {
            return x>=0 && x<maxX && y>=0 && y<maxY ? true : false;
        }
    }
    
    class WaterPos {
        int x;
        int y;
    
        public WaterPos(int x, int y) {
            this.x = x;
            this.y =y;
        }
    }
    반응형

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

    BOJ) 조약돌 꺼내기  (0) 2020.06.13
    BOJ) 귀여운 수~ε٩(๑> ₃ <)۶з  (0) 2020.06.12
    BOJ) 연속합  (0) 2020.06.12
    BOJ) 피자  (0) 2020.06.11
    BOJ) 좋은 대회  (0) 2020.06.11

    댓글

Designed by Tistory.