• [백준OJ] 13460번 구슬 탈출 2

    2021. 8. 5.

    by. Hyeon-Uk

    반응형

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

     

    13460번: 구슬 탈출 2

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

    www.acmicpc.net


     

    -풀이-

    간단한 BFS이다. 주의할점만 생각해주면 구현이 복잡하진 않다.

    1. 구슬을 굴리고 난 뒤, 빨간공과 파란공이 겹치면 조정이 필요하다.

     1-1 밑으로 내려가는 방향이였을때 겹치면, 더 위에있던공의 i좌표 -1
     1-2 위로 올라가는 방향이였을때 겹치면, 더 아래있던공의 i좌표 +1
     1-3 오른쪽으로 가는 방향이였을때 겹치면, 더 왼쪽에있던 공의 j좌표 -1
     1-4 왼쪽으로 가는 방향이였을때 겹치면, 더 오른쪽에 있던 공의 j좌표 +1

    이렇게 해주면 굴리고 난 뒤 겹치지 않을것이다.

     

    2. 구슬을 굴리고 빨간공이 골 위치에 있을때, 만약 파란공도 골 위치에 있다면 넘겨야한다.

     

    3. visited를 빨간공 따로, 파란공 따로 체크를 해주면 안된다. 빨간공과 파란공의 위치를 동시에 체크해주어야한다.

     

    4. 10번 이하로 넣지 못하면 -1 출력하자. 저는 이 조건을 보지못해서 무지성 WA를 받았습니다...문제는 꼭 끝까지 꼼꼼하게!

     

    -코드-

    #include <iostream>
    #include<algorithm>
    #include<utility>
    #include<vector>
    #include<queue>
    using namespace std;
    
    char maze[10][10];
    bool visited[10][10][10][10] = { 0 };
    int mv[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
    pair<int, int> goal, red, blue;
    int n, m;
    
    bool isIn(int i, int j) {
    	return (maze[i][j] != '#');
    }
    
    bool isGoal(int i, int j) {
    	return (maze[i][j] == 'O');
    }
    
    pair<int, int> moving(int i, int j, int d) {
    	pair<int, int> result = { i,j };
    
    	while (true){
    		result.first += mv[d][0];
    		result.second += mv[d][1];
    
    		if (!isIn(result.first, result.second)) {
    			result.first -= mv[d][0];
    			result.second -= mv[d][1];
    			break;
    		}
    		if (isGoal(result.first, result.second)) {
    			break;
    		}
    	}
    	return result;
    }
    
    int bfs() {
    	queue<pair<pair<pair<int, int>, pair<int, int>>,int>>q;
    
    	q.push({ {red,blue} ,0 });
    	visited[red.first][red.second][blue.first][blue.second] = true;
    
    	while (!q.empty()) {
    		int ri = q.front().first.first.first;
    		int rj = q.front().first.first.second;
    		int bi = q.front().first.second.first;
    		int bj = q.front().first.second.second;
    		int cnt = q.front().second;
    		q.pop();
    
    		if (cnt > 9) {
    			continue;
    		}
    
    		for (int i = 0; i < 4; i++) {
    			pair<int, int> rn, bn;
    			rn = moving(ri, rj, i);
    			bn = moving(bi, bj, i);
    
    			if (rn == goal) {
    				if (bn == goal) {
    					continue;
    				}
    				else {
    					return cnt + 1;
    				}
    			}
    			else if (bn == goal) {
    				continue;
    			}
    
    			//움직이고 겹쳤으면, 조정
    			if (rn == bn) {
    				//밑으로 내려가는 방향이였을때 겹치면, 더 위에있던공의 i좌표 --
    				if (i == 0) {
    					if (ri < bi) {
    						rn.first--;
    					}
    					else {
    						bn.first--;
    					}
    				}
    				//위로 올라가는 방향이였을때 겹치면, 더 아래있던공의 i좌표 ++;
    				else if (i == 1) {
    					if (ri < bi) {
    						bn.first++;
    					}
    					else {
    						rn.first++;
    					}
    				}
    				//오른쪽으로 가는 방향이였을때 겹치면, 더 왼쪽에있던 공의 j좌표 --;
    				else if (i == 2) {
    					if (rj < bj) {
    						rn.second--;
    					}
    					else {
    						bn.second--;
    					}
    				}
    				//왼쪽으로 가는 방향이였을때 겹치면, 더 오른쪽에 있던 공의 j좌표 ++;
    				else {
    					if (rj < bj) {
    						bn.second++;
    					}
    					else {
    						rn.second++;
    					}
    				}
    			}
    
    			if (!visited[rn.first][rn.second][bn.first][bn.second]) {
    				q.push({ {rn,bn},cnt + 1 });
    				visited[rn.first][rn.second][bn.first][bn.second] = true;
    			}
    		}
    	}
    	return -1;
    }
    
    void input() {
    	cin >> n >> m;
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < m; j++) {
    			cin >> maze[i][j];
    			if (maze[i][j] == 'O') {
    				goal = { i,j };
    			}
    			if (maze[i][j] == 'B') {
    				blue = { i,j };
    			}
    			if (maze[i][j] == 'R') {
    				red = { i,j };
    			}
    		}
    	}
    }
    
    void solve() {
    	input();
    	cout<<bfs();
    }
    
    int main(){
    	ios::sync_with_stdio(false);
    	cin.tie(NULL);
    	cout.tie(NULL);
    	
    	solve();
    
    	return 0;
    }

     

    반응형

    '문제풀이 > 백준oj' 카테고리의 다른 글

    [백준OJ] 5427번 불  (0) 2021.08.08
    [백준OJ] 8972번 미친 아두이노  (0) 2021.08.06
    [백준OJ] 6118번 숨바꼭질  (0) 2021.08.04
    [백준OJ] 1305번 광고  (0) 2021.08.04
    [백준OJ] 13302번 리조트  (0) 2021.08.03

    댓글