백준 13460 구슬탈출2(Java,자바)

jonghyukLee·2021년 9월 20일
0

이번에 풀어본 문제는
백준 13460번 구슬탈출2 입니다.

📕 문제 링크

❗️코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

class Ball
{
    int bx,by,rx,ry,cnt;

    public Ball(int bx, int by, int rx, int ry, int cnt)
    {
        this.bx = bx;
        this.by = by;
        this.rx = rx;
        this.ry = ry;
        this.cnt = cnt;
    }
}
public class Main {
    static int n,m;
    static char [][] map;
    static boolean [][][][] isVis;
    static int [] dx = {-1,1,0,0};
    static int [] dy = {0,0,-1,1};
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        map = new char[n][m];

        int bx=0,by=0,rx=0,ry=0;
        for(int i = 0; i < n; ++i)
        {
            String tmp = br.readLine();
            for(int j = 0; j < m; ++j)
            {
                map[i][j] = tmp.charAt(j);
                if(map[i][j] == 'B')
                {
                    bx = i;
                    by= j;
                }
                else if(map[i][j] == 'R')
                {
                    rx = i;
                    ry = j;
                }
            }
        }
        isVis = new boolean[n][m][n][m];
        Queue<Ball> q= new LinkedList<>();
        q.add(new Ball(bx,by,rx,ry,1));
        boolean exitFlag = false;
        loop : while(!q.isEmpty())
        {
            Ball cur = q.poll();
            if(cur.cnt > 10)
            {
                System.out.print("-1");
                return;
            }
            if(isVis[cur.bx][cur.by][cur.rx][cur.ry]) continue;

            for(int i = 0; i < 4; ++i)
            {
                int b_mx = cur.bx;
                int b_my = cur.by;
                boolean [] isExit = new boolean[2];
                while(true)
                {
                    b_mx += dx[i];
                    b_my += dy[i];
                    if(!isValid(b_mx,b_my) || map[b_mx][b_my] == '#')
                    {
                        b_mx -= dx[i];
                        b_my -= dy[i];
                        break;
                    }
                    if(map[b_mx][b_my] == 'O')
                    {
                        isExit[0] = true;
                        break;
                    }
                }
                int r_mx = cur.rx;
                int r_my = cur.ry;
                while(true)
                {
                    r_mx += dx[i];
                    r_my += dy[i];
                    if(!isValid(r_mx,r_my) || map[r_mx][r_my] == '#')
                    {
                        r_mx -= dx[i];
                        r_my -= dy[i];
                        break;
                    }
                    if(map[r_mx][r_my] == 'O')
                    {
                        isExit[1] = true;
                        break;
                    }
                }
                if(b_mx == cur.bx && b_my == cur.by && r_mx == cur.rx && r_my == cur.ry) continue;
                if(isExit[1])
                {
                    if(isExit[0]) continue;
                    else
                    {
                        System.out.print(cur.cnt);
                        exitFlag = true;
                        break loop;
                    }
                }
                else if(isExit[0]) continue;
                if(b_mx == r_mx && b_my == r_my)
                {
                    if(i == 0)
                    {
                        if(cur.bx < cur.rx) r_mx += 1;
                        else b_mx += 1;
                    }
                    else if(i == 1)
                    {
                        if(cur.bx < cur.rx) b_mx -= 1;
                        else r_mx -= 1;
                    }
                    else if(i == 2)
                    {
                        if(cur.by < cur.ry) r_my += 1;
                        else b_my += 1;
                    }
                    else
                    {
                        if(cur.by < cur.ry) b_my -= 1;
                        else r_my -= 1;
                    }
                }
                q.add(new Ball(b_mx,b_my,r_mx,r_my,cur.cnt+1));
            }
            isVis[cur.bx][cur.by][cur.rx][cur.ry] = true;
        }
        if(!exitFlag) System.out.print("-1");

    }
    static boolean isValid(int x, int y)
    {
        return x > 0 && y > 0 && x < n-1 && y < m-1;
    }
}

📝 풀이

bfs로 풀어보았습니다.
조건이 굉장히 복잡하지만 시키는대로만 하면 어렵지는 않았던 것 같습니다.
우선 두 구슬이 같은선상에 있을 경우가 가장 헷갈렸는데, 일단 굴려놓고 두 구슬이 겹쳐있을 때, 이전 위치를 통해 어떤 구슬을 한칸 뒤로 빼야하는지 결정해줍니다.
두 구슬이 모두 빠지거나 파란 구슬만 빠지는 경우는 제외해주고, 가장 먼저 빨간구슬을 내보내는 경우 결과를 출력하고 종료합니다. 4차원 방문배열을 만들어 각 구슬들의 이동 전 좌표값을 기반으로 방문체크를 해줄 수 있습니다.

📜 후기

정말.. 어이없지만 구멍을 숫자0으로 봐서 잘못된 부분 찾는다고 30분은 버린 것 같습니다 ㅎㅏ ㅎ ㅏ ㅎ ㅎㅎ ㅏㅏ,,,
복잡하지만 구현문제는 머릿속에 뭔가 상황이 그려져서 재밌는 것 같아요! ㅋㅋㅋㅋㅋ
추석이라 할머니댁에 와있지만 시간 짬내서 한문제 풀어보았습니다!
즐추~

profile
머무르지 않기!

0개의 댓글