문제풀이/백준oj
[백준OJ] 13460번 구슬 탈출 2
Hyeon-Uk
2021. 8. 5. 01:11
반응형
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;
}
반응형