반응형
12-04 04:17
Today
Total
«   2024/12   »
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
관리 메뉴

개발하는 고라니

[백준] 13460번 : 구슬 탈출 2 본문

Programming/백준

[백준] 13460번 : 구슬 탈출 2

조용한고라니 2021. 3. 23. 02:38
반응형
 

13460번: 구슬 탈출 2

첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'

www.acmicpc.net


[BFS]

정답률 25%를 과시라도 하듯 결코 쉽지않은 문제이다. 문제에 주어진 조건 중 몇 가지가 특히 어떻게 접근해야할지 난해했다. 그 중에 '빨간 구슬(R)과 파란 구슬(B)은 동시에 같은 칸에 있을 수 없다. 또, 빨간 구슬과 파란 구슬의 크기는 한 칸을 모두 차지한다.가 특히나 골치아팠다.

 

    static class Point{
        int y, x;
        
        public Point(int yy, int xx){
            y=yy; x=xx;
        }
    }
    static class Biz{
        Point red, blue;
        int move;
        
        public Biz(Point r, Point b, int m){
            red = r;
            blue = b;
            move = m;
        }
    }
    //Point : R과 B의 위치를 나타내기 위한 좌표
    //Biz : R과 B의 구슬 데이터를 담고있고, 움직임의 횟수를 갖는다

 

# 풀이 요약

R과 B의 처음 위치에서 BFS를 수행

1. R이 '#' / 'O'을 만날 때 까지 한 방향으로 쭉 간다.

2. B가 '#' / 'O'을 만날 때 까지 한 방향으로 쭉 간다.

3. if( R위치 == B위치 and 'O'가 아닐 때) ?

3-1) 현재 방향이 상하좌우에 따라 다르다(코드 참조)

4. Queue에 넣기

 

5. R이 'O'이고 B는 'O'이 아닐 때 result 값 갱신 후 BFS 종료

# Code </>

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 {

    static class Point{
        int y, x;
        
        public Point(int yy, int xx){
            y=yy; x=xx;
        }
    }
    static class Biz{
        Point red, blue;
        int move;
        
        public Biz(Point r, Point b, int m){
            red = r;
            blue = b;
            move = m;
        }
    }

    static int r, c;
    static int[] Y = {-1, 1, 0, 0}, X = {0, 0, -1, 1};
    static char[][] map = new char[11][11];

    static int BFS(Biz start){

        int result = -1;
        Queue<Biz> Q = new LinkedList<>();
        Q.add(start);

        while(!Q.isEmpty()){
            Biz biz = Q.poll();
            
            Point red = biz.red;
            Point blue = biz.blue;
            
            int move = biz.move;

            //10번 이하의 이동 중 Red 구슬만 'O'에 들어가는 경우가 없을 땐 result = -1로 동일하다.
            if(map[red.y][red.x] == 'O' && map[blue.y][blue.x] != 'O') {
                result = move;
                break;
            }

            for(int a=0; a<4; a++){
            
                int nyR = red.y - Y[a];
                int nxR = red.x - X[a];
                int nyB = blue.y - Y[a];
                int nxB = blue.x - X[a];

                //move가 10이하일 때만 가능
                if(move <= 9) {
                    //Red구슬을 상하좌우로 기울여 더 움직일 수 없을 때 까지 혹은 'O'를 만날 때 까지
                    while (true) {
                        nyR += Y[a];
                        nxR += X[a];

                        int ny = nyR + Y[a];
                        int nx = nxR + X[a];
                        
                        if(map[nyR][nxR] == 'O' || map[ny][nx] == '#')
                            break;
                    }

                    //Blue구슬을 상하좌우로 기울여 더 움직일 수 없을 때 까지 혹은 'O'를 만날 때 까지
                    while (true) {
                        nyB += Y[a];
                        nxB += X[a];

                        int ny = nyB + Y[a];
                        int nx = nxB + X[a];

                        if(map[nyB][nxB] == 'O' || map[ny][nx] == '#')
                            break;
                    }

                    //Red와 Blue의 위치가 동일 and 현재 위치가 'O'가 아닐 때
                    //Red와 Blue구슬은 한 칸에 동시에 위치할 수 없음!
                    if(nyR == nyB && nxR == nxB && map[nyR][nxR] != 'O'){
                    
                        int gapY = red.y - blue.y;
                        int gapX = red.x - blue.x;
                        
                        switch (a){
                            //상,하,좌,우
                            case 0:
                                if(gapY > 0) nyR -= Y[a];
                                else nyB -= Y[a];
                                break;
                                
                            case 1:
                                if(gapY > 0) nyB -= Y[a];
                                else nyR -= Y[a];
                                break;
                                
                            case 2:
                                if(gapX > 0) nxR -= X[a];
                                else nxB -= X[a];
                                break;
                                
                            case 3:
                                if(gapX > 0) nxB -= X[a];
                                else nxR -= X[a];
                                break;
                        }
                    }
                    Point nRed = new Point(nyR, nxR);
                    Point nBlue = new Point(nyB, nxB);
                    
                    Q.add(new Biz(nRed, nBlue, move + 1));
                }
            }
        }

        return result;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        Point[] biz = new Point[2];

        r = Integer.parseInt(st.nextToken());
        c = Integer.parseInt(st.nextToken());

        for(int i=1; i<=r; i++){
            char[] str = br.readLine().toCharArray();
            for(int j=1; j<=c; j++) {
                map[i][j] = str[j - 1];

                if(map[i][j] == 'R')
                    biz[0] = new Point(i, j);
                    
                if(map[i][j] == 'B')
                    biz[1] = new Point(i, j);
            }
        }
        System.out.println(BFS(new Biz(biz[0], biz[1], 0)));
    }
}
반응형

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

[백준] 1929번 : 소수 구하기  (0) 2021.03.23
[백준] 1978번 : 소수 찾기  (0) 2021.03.23
[백준] 2776번 : 암기왕  (1) 2021.03.21
[백준] 2098번 : 외판원 순회  (0) 2021.03.21
[백준] 15900번 : 나무 탈출  (0) 2021.03.20
Comments