문제의 알고리즘 자체는 어려운편은 아니지만, 예외 케이스가 많고 기저 사건이 다양하기 때문에 문제를 잘읽고
코드는 최대한, 실수가 나지 않게끔 길어지더라도, 명확하게 분류해서 잘짜는게 중요한듯 합니다.
알고리즘은 기본적인 BFS 최단 문제입니다.
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
int N, M;
string Map[10];
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};
int oy, ox;
int bx, by;
int rx, ry;
struct pos {
int bx, by;
int rx, ry;
int cnt;
pos(int by, int bx,int ry,int rx, int cnt) :by(by), bx(bx), ry(ry), rx(rx),cnt(cnt) {}
};
bool visit[10][10][10][10];
int BFS() {
queue<pos> q;
q.push(pos(by, bx, ry, rx,0));
while (!q.empty()) {
// queue에서 pop
int cpos[4] = {q.front().by, q.front().bx, q.front().ry, q.front().rx};
int cnt = q.front().cnt; q.pop();
if (cnt > 10) break; //횟수 제한 초과
visit[cpos[0]][cpos[1]][cpos[2]][cpos[3]] = true;
//정답
if (cpos[2] == oy && cpos[3] == ox) return cnt;
// 상 하 좌 우
for (int i = 0; i < 4; i++) {
int npos[4] = { cpos[0],cpos[1],cpos[2],cpos[3] }; //next pos
// 0에 빠졌는지 flag
bool flag = true;
bool flag2 = true;
//blue가 쭉 움직인다.
while (Map[npos[0]+dy[i]][npos[1]+dx[i]] != '#' && flag) {
npos[0] += dy[i];
npos[1] += dx[i];
if (Map[npos[0]][npos[1]] == 'O') flag = false;
}
//red가 쭉움직인다.
while (Map[npos[2] + dy[i]][npos[3] + dx[i]] != '#' && flag2) {
npos[2] += dy[i];
npos[3] += dx[i];
if (Map[npos[2]][npos[3]] == 'O') flag2 = false;
}
//블루가 구멍에 빠져버렸으면 이번 경우의 수는 스킵한다.
if (!flag) continue;
if (npos[0] == npos[2] && npos[1] == npos[3]) {
// red blue 위치가 같은 경우
// 원래 순서와 움직인 방향에 따라 red blue 순서를 재배치
switch (i)
{
case 0:
if (cpos[1] < cpos[3]) npos[3] -= dx[i];
else npos[1] -= dx[i];
break;
case 1:
if (cpos[1] < cpos[3]) npos[1] -= dx[i];
else npos[3] -= dx[i];
break;
case 2:
if (cpos[0] < cpos[2]) npos[2] -= dy[i];
else npos[0] -= dy[i];
break;
case 3:
if (cpos[0] < cpos[2]) npos[0] -= dy[i];
else npos[2] -= dy[i];
break;
}
}
if (!visit[npos[0]][npos[1]][npos[2]][npos[3]]) {
q.push(pos(npos[0], npos[1], npos[2], npos[3], cnt + 1));
}
}
}
return -1;
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> N >> M;
for (int i = 0; i < N; i++) {
cin >> Map[i];
}
//맵을 흝으며, B,R,O의 좌표를 저장
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
char tmp = Map[i][j];
if (tmp == 'B') {
by = i; bx = j;
}
if (tmp == 'R') {
ry = i; rx = j;
}
if (tmp == 'O') {
oy = i; ox = j;
}
}
}
cout << BFS();
}
이렇게 예외케이스가 많은경우,
switch문을 사용하여 이쁘게 정리하는게 코드를 눈으로 볼 때 좋았던거 같습니다.
저는 쉽게 가려고 npos[4] , cpos[4] 등 배열을 그냥 썼는데, 변수의 의미가 제대로 보이지 않아 실수하기 쉬웠습니다.
이런 복잡한 케이스를 가지는 문제들은 Blue_xPos, Blue_yPos 등 정확한 변수이름을 써서 코딩하는 것이 실수를 줄일 수 있습니다.
'Algorithm' 카테고리의 다른 글
백준 12100 삼성기출 2480(Easy) (0) | 2020.04.20 |
---|---|
백준 2352번 nlog(n)으로 풀기, LIS 알고리즘의 이해 (longest increasing Subsequence ) (0) | 2020.04.10 |
백준 2631 줄세우기 LIS 개념 다이나믹 프로그래밍 (0) | 2020.04.07 |
다이나믹 프로그래밍으로 최적화 하는 DFS, 백준 2253번 점프 (0) | 2020.03.28 |
백준 1525번 퍼즐 BFS 최단,최소 문제. DFS는 힘든이유.. (0) | 2020.03.22 |
댓글