• BOJ 13460 구슬 탈출 2 / C++

    2022. 7. 26.

    by. 내이름은 킹햄찌

    https://www.acmicpc.net/problem/13460

     

    13460번: 구슬 탈출 2

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

    www.acmicpc.net

    백준 온라인저지 13460번 구슬 탈출 2 문제입니다.

     

    아이디어

    구슬 클래스를 하나 정의해서 대부분 해당 클래스에서 처리하도록 했고, BFS를 통해 최소거리를 찾았습니다.

    문제의 핵심은 파란공이 들어갔을때에 대한 처리와 두 구슬을 움직이다 곂칠때에 대한 처리라고 생각했습니다.

    파린공이 들어갔을때는 해당 케이스는 통과하도록 처리했고, 곂쳐질때는 이동거리가 더 긴공이 반대로 이동하도록 처리했습니다. 자세한건 아래 주석을 통해 확인할 수 있습니다.

    #include <iostream>
    #include <vector>
    #include <queue>
    #define MAX 10
    using namespace std;
    
    int mx[4] = { 0,1,0,-1 };
    int my[4] = { 1,0,-1,0 };
    int ry, rx, by, bx;
    bool visited[10][10][10][10];
    int n, m;
    
    vector<vector<char>> field;
    
    //dirction
    enum {
    	up = 0,
    	right = 1,
    	down = 2,
    	left = 3
    };
    
    //field element
    enum {
    	Wall = '#',
    	Hole = 'O',
    	Red = 'R',
    	Blue = 'B',
    	None = '.'
    };
    
    //구슬
    class Bead {
    private:
    	int y;
    	int x;
    	int dirCnt;
    public:
    	Bead() {}
    	Bead(int a, int b , int c) {
    		y = a;
    		x = b;
    		dirCnt = c;
    	}
    
    	//방향만 받아서 움직일수 있을때까지 움직임
    	int move(int dir) {
    		int moveCnt = 0;
    		while (true) {
    			//현재가 구멍일때
    			if (field[y][x] == Hole) break;
    			//다음이 벽일때
    			if (field[y + my[dir]][x + mx[dir]] == Wall) break;
    			y += my[dir];
    			x += mx[dir];
    			moveCnt++;
    			
    		}
    		dirCnt++;
    		return moveCnt;
    	}	
    
    
    	int getDircCnt() {
    		return dirCnt;
    	}
    
    	int getX() {
    		return x;
    	}
    	int getY() {
    		return y;
    	}
    };
    
    
    void setField() {
    	field = vector<vector<char>>(n, vector<char>(m, ' '));
    }
    
    void input() {
    	cin >> n >> m;
    	setField();
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < m; j++) {
    			cin >> field[i][j];
    			if (field[i][j] == Red) {
    				ry = i;
    				rx = j;
    			}
    			else if (field[i][j] == Blue) {
    				by = i;
    				bx = j;
    			}
    
    		}
    	}
    }
    
    void bfs() {
    	queue<pair<Bead, Bead>> q;
    	q.push({ Bead(ry,rx,0),Bead(by,bx,0) });
    	visited[ry][rx][by][bx] = true;
    	while (!q.empty()) {
    		Bead red = q.front().first;
    		Bead blue = q.front().second;
    		q.pop();
    
    		if (red.getDircCnt() > 9) break;
    
    		for (int i = 0; i < 4; i++) {
    			Bead r = red;
    			Bead b = blue;
    			int rMove = r.move(i);
    			int bMove = b.move(i);
    
    			//파란구슬이 먼저 들어가면 처리하지 않음
    			if (field[b.getY()][b.getX()] == Hole) continue;
    			if (field[r.getY()][r.getX()] == Hole) {
    				cout << r.getDircCnt();
    				return;
    			}
    
    			//두 구슬이 곂쳐질때
    			if (r.getY() == b.getY() && r.getX() == b.getX()) {
    
    				//이동 거리가 더 많은 구슬이 한칸 반대로 움직임
    				if (rMove > bMove) {
    					r = Bead(r.getY() - my[i], r.getX() - mx[i], r.getDircCnt());
    				}
    				else {
    					b = Bead(b.getY() - my[i], b.getX() - mx[i], b.getDircCnt());
    				}
    			}
    			
    			if (visited[r.getY()][r.getX()][b.getY()][b.getX()]) continue;
    			visited[r.getY()][r.getX()][b.getY()][b.getX()] = true;
    			q.push({ r,b });
    
    		}
    	}
    	cout << "-1";
    }
    
    void solution() {
    	bfs();
    }
    
    int main(void) {
    	input();
    	solution();
    }

     

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

    BOJ 3190 뱀 / C++  (0) 2022.07.26
    BOJ 14499 주사위 굴리기 / C++  (0) 2022.07.26
    BOJ 15591 MooTube / C++  (0) 2022.05.24
    BOJ 1476 날짜 계산 / C++  (0) 2022.05.24
    BOJ 2231 분해합 / C++  (0) 2022.05.24

    댓글