반응형
리뷰
설계를 하지 않고 무작정 덤볐다가 호되게 당한 문제, 구현과 시뮬레이션은 둘째치고 생각 못하고 있던 조건들이 많아서 애를 먹었다, 해당 문제를 풀기 전에 문제에 대한 조건을 한번 쭉 정리하는걸 추천한다.
https://www.acmicpc.net/problem/13460
문제 풀이
전역변수
- n, m : 2차원 맵 상 행과 열의 크기를 저장할 변수
- sx1, sy1, sx2, sy2 : 빨간색 구슬과 파란색 구슬의 x, y좌표를 저장할 변수
- lst : 맵 정보를 저장할 문자열 배열, 최대 크기가 10이므로 10만큼의 크기를 지정해 주었다.
- v : 방문 처리를 할 4차원 정수 배열, 각각의 요소에 sx1, sy1, sx2, sy2의 위치 저장, 맵의 크가보다 1크게 초기화
- dx, dy : 4방향 탐색을 위한 방향 배열
- Pos : 현재 빨간구슬과 파란구슬의 위치와 움직인 턴을 저장할 구조체, 시뮬레이션 용이다.
- n, m값을 받아와 n번의 for문으로 맵 정보를 lst에 저장해 준다.
- 맵 정보를 입력 받으며 구슬을 발견하면 각 변수에 값을 매핑해 주고 현재 자리를 '.'로 바꾸어 준다.
- 입력이 완료되었다면 bfs함수를 호출해 준다.
- 구조체 Pos타입 큐를 초기화 해주고 해당 큐에 빨간색 구슬과 파란색 구슬의 위치와 0을 삽입해 준다.
- 추가로 현재 빨간 구슬과 파란 구슬의 위치를 방문처리 해준다.
- q가 빌때까지 탐색을 시작하며 만약 현재 시뮬레이션의 횟수가 10회차일 경우 continue 처리해 준다.
- 4방향 탐색을 통해 구슬의 위치를 적절하게 이동시켜 주어야 한다. 우선 현재 위치를 그대로 복사해 준다.
- 이동을 시작하기 전에 어떤 구슬부터 이동을 해주어야 할지 정의를 해주어야 한다.
- 만약 우측 이동일 경우 더 오른쪽에 있는 구슬부터 이동을 해준다. 행이 다르면 상관 없다.
- 좌측 이동일 경우 더 왼쪽에 있는 구슬부터 이동을 해준다. 마찬가지로 행이 다르면 상관 없다.
- 위쪽 이동일 경우 더 위에 있는 구슬부터 이동을 해준다. 열이 다르면 상관 없다.
- 아래쪽 이동일 경우 더 아래에 있는 구슬부터 이동을 해준다 마찬가지로 열이 다르면 상관 없다.
- flag를 각 구슬마다 초깃값 1로 설정해 주고 더 이상 움직이지 못할 경우 flag를 0으로 만들어 준다.
- 만약 이동중에 '0' 즉, 출구를 만난다면 위치를 10으로 변경해 주고 flag를 0으로 만들어 준다.
- 모든 이동을 마치고 만약 현재 위치가 방문처리가 되어있는 경우 continue 처리를 해준다.
- 파란색 구슬의 위치가 10일 경우 해당 공이 빠져나온 것이므로 continue 처리를 해준다.
- 빨간색 구슬의 위치가 10일 경우 nt값을 리턴하고 탐색을 중단해 준다. 빨간색 구슬만 탈출한 케이스다.
- 위 조건에 모두 해당하지 않을 경우 현재 위치를 방문처리 해준 뒤 큐에 다시 삽입해 준다.
- 큐에 삽입할 때에는 최종 이동한 위치와 시간을 늘려준 상태로 추가를 해주면 된다.
- 만약 큐가 빌때까지 빨간색 구슬만 탈출하지 못했을 경우 -1을 리턴해 주면 된다. 리턴된 값을 그대로 출력해 준다.
참고 사항
- 모든 구슬은 동시에 시뮬레이션 되어야 한다.
- 공이 움직이는 순서를 명확하게 정의해 주어야 한다.
- 방문배열을 맵보다 1크게 해준 것은 공이 0에 달했을때 위치를 10으로 변경하므로 세그먼트 폴트를 방지하기 위함
정답 코드
#include<iostream>
#include<queue>
using namespace std;
int n, m, sx1, sy1, sx2, sy2;
string lst[10];
int v[11][11][11][11] = {0,};
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };
struct Pos {
int rx, ry, bx, by, t;
};
int bfs() {
queue<Pos> q;
q.push({ sx1, sy1, sx2, sy2, 0 });
v[sx1][sy1][sx2][sy2] = 1;
while (!q.empty()) {
Pos pos = q.front(); q.pop();
int crx = pos.rx, cry = pos.ry, cbx = pos.bx, cby = pos.by, ct = pos.t;
if (ct == 10) continue;
for (int i = 0; i < 4; i++) {
int nrx = crx, nry = cry, nbx = cbx, nby = cby, nt = ct + 1;
int flag1 = 1, flag2 = 1;
if ((i == 0 && cry >= cby) || (i == 1 && cry < cby) || (i == 2 && crx >= cbx) || (i == 3 && crx < cbx)) {
while (flag1 || flag2) {
if (flag1 && 0 <= nrx + dx[i] && nrx + dx[i] < n && 0 <= nry + dy[i] && nry + dy[i] < m && lst[nrx + dx[i]][nry + dy[i]] != '#' && (nrx + dx[i] != nbx || nry + dy[i] != nby)) {
nrx += dx[i]; nry += dy[i];
if (lst[nrx][nry] == 'O') {
nrx = 10, nry = 10;
flag1 = 0;
}
}
else flag1 = 0;
if (flag2 && 0 <= nbx + dx[i] && nbx + dx[i] < n && 0 <= nby + dy[i] && nby + dy[i] < m && lst[nbx + dx[i]][nby + dy[i]] != '#' && (nbx + dx[i] != nrx || nby + dy[i] != nry)) {
nbx += dx[i]; nby += dy[i];
if (lst[nbx][nby] == 'O') {
nbx = 10, nby = 10;
flag2 = 0;
}
}
else flag2 = 0;
}
}
else {
while (flag1 || flag2) {
if (flag2 && 0 <= nbx + dx[i] && nbx + dx[i] < n && 0 <= nby + dy[i] && nby + dy[i] < m && lst[nbx + dx[i]][nby + dy[i]] != '#' && (nbx + dx[i] != nrx || nby + dy[i] != nry)) {
nbx += dx[i]; nby += dy[i];
if (lst[nbx][nby] == 'O') {
nbx = 10, nby = 10;
flag2 = 0;
}
}
else flag2 = 0;
if (flag1 && 0 <= nrx + dx[i] && nrx + dx[i] < n && 0 <= nry + dy[i] && nry + dy[i] < m && lst[nrx + dx[i]][nry + dy[i]] != '#' && (nrx + dx[i] != nbx || nry + dy[i] != nby)) {
nrx += dx[i]; nry += dy[i];
if (lst[nrx][nry] == 'O') {
nrx = 10, nry = 10;
flag1 = 0;
}
}
else flag1 = 0;
}
}
if (v[nrx][nry][nbx][nby]) continue;
if (nbx == 10 && nby == 10) continue;
if (nrx == 10 && nry == 10) return nt;
v[nrx][nry][nbx][nby] = 1;
q.push({ nrx, nry, nbx, nby, nt });
}
}
return -1;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> lst[i];
for (int j = 0; j < m; j++) {
if (lst[i][j] == 'B') {
sx2 = i, sy2 = j;
lst[i][j] = '.';
}
else if (lst[i][j] == 'R') {
sx1 = i, sy1 = j;
lst[i][j] = '.';
}
}
}
cout << bfs();
}
728x90
반응형
'알고리즘 공부 > C++' 카테고리의 다른 글
[G4] 백준 2239번 스도쿠 C++ 백트래킹, 구현 (0) | 2024.09.20 |
---|---|
[P5] 백준 2887번 행성 터널 C++ MST, 최소 신장 트리 (0) | 2024.09.19 |
[G2] 백준 16946번 벽 부수고 이동하기 4 C++ BFS, FloodFill, 너비 우선 탐색 (0) | 2024.09.17 |
[G5] 백준 2166번 다각형의 면적 C++ 기하학, 신발끈 공식, 슈메르카우스키의 공식 (2) | 2024.09.16 |
[G2] 백준 1400번 화물차 C++ 다익스트라, 최단 경로, 구현 (6) | 2024.09.16 |