문제
"맞았습니다" 코드
#include <bits/stdc++.h>
#define X first
#define Y second
using namespace std;
int L, R, C; // 층, 행, 열
int bd[35][35][35];
int vis[35][35][35]; // 거리 저장
int dx[] = {0, 0, 0, 0, 1, -1}; // 층
int dy[] = {0, 1, 0, -1, 0, 0}; // 행
int dz[] = {1, 0, -1, 0, 0, 0}; // 열
queue<pair<pair<int,int>, int>> qu; // 층, 행, 열
int exittime; // 탈출시간
bool rangecheck(int i, int j, int k){ // 층, 행, 열 유효범위 검사
return (i >=0 && i < L && j >= 0 && j < R && k >=0 && k < C);
}
void initvis(){ // 방문배열 초기화
for(int i = 0; i < 35; i++)
for(int j = 0; j < 35; j++) {
fill(vis[i][j], vis[i][j] + 35, -1);
fill(bd[i][j], bd[i][j] + 35, 0);
}
}
int bfs(){
while(!qu.empty()) {
int curx = qu.front().X.X;
int cury = qu.front().X.Y;
int curz = qu.front().Y;
qu.pop();
if(bd[curx][cury][curz] == 3) return vis[curx][cury][curz];
for (int i = 0; i < 6; i++) {
int nx = dx[i] + curx;
int ny = dy[i] + cury;
int nz = dz[i] + curz;
// 벽(1)이면 못감. 유효범위, 방문여부 확인
if (!rangecheck(nx, ny, nz) || bd[nx][ny][nz] == 1 || vis[nx][ny][nz] >= 0) continue;
vis[nx][ny][nz] = 1+vis[curx][cury][curz]; // 방문
qu.push({{nx,ny},nz});
}
}
return -1;
}
void input(){ // 입력받기
// 초기화
initvis();
while(!qu.empty()) qu.pop(); // 큐 비우기
// 입력받기
char ch;
for(int i = 0; i < L; i++) { // 층
for (int j = 0; j < R; j++) { // 행
for (int k = 0; k < C; k++) { // 열
cin >> ch;
if (ch == '#') { // 벽 1
bd[i][j][k] = 1;
} else if (ch == 'S') { // 시작 위치 2
bd[i][j][k] = 2;
vis[i][j][k] = 0;
qu.push({{i,j},k});
} else if (ch == 'E') { // 출구 3
bd[i][j][k] = 3;
}
}
}
}
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
while(1){
cin >> L >> R >> C; // 입력받기
if(L==0 && R ==0 && C==0) break; // 종료조건
input();
int result = bfs();
if(result < 0) cout << "Trapped!" << '\n';
else cout << "Escaped in "<<result << " minute(s)." << '\n';
}
return 0;
}
리뷰
문제를 주의 깊게 안읽어서 고생했다.
3차원 토마토 문제랑 거의 똑같다. 시작 위치와 탈출 위치가 정해져 있다.
vis 배열은 거리를 저장하고 방문여부를 구분하기 위해 -1로 초기화했다.
bd 배열은 1이면 벽으로 표시해서 방문하지 못하게 했다.
vis 배열에는 거리를 저장했다. 그래서 시작 위치에서는 0이다.
테스트케이스가 여러개니까 방문배열과 큐를 반드시 초기화한 다음에 bfs를 돌아야 한다.
큐에 '거리'(==이동 횟수) 를 저장하는 방법으로도 풀었다.
#include <bits/stdc++.h>
#define X first
#define Y second
using namespace std;
int L, R, C; // 층, 행, 열
int bd[35][35][35];
bool vis[35][35][35];
int dx[] = {0, 0, 0, 0, 1, -1}; // 층
int dy[] = {0, 1, 0, -1, 0, 0};
int dz[] = {1, 0, -1, 0, 0, 0};
queue<pair<pair<int,int>, pair<int,int>>> qu; // 층, 행, 열, 이동횟수
bool rangecheck(int i, int j, int k){ // 층, 행, 열 유효범위 검사
return (i >=0 && i < L && j >= 0 && j < R && k >=0 && k < C);
}
void initvis(){ // 방문배열 초기화
for(int i = 0; i < 35; i++)
for(int j = 0; j < 35; j++) {
fill(vis[i][j], vis[i][j] + 35, false);
fill(bd[i][j], bd[i][j] + 35, 0);
}
}
int bfs(){
while(!qu.empty()) {
int curx = qu.front().X.X;
int cury = qu.front().X.Y;
int curz = qu.front().Y.X;
int curcnt = qu.front().Y.Y;
qu.pop();
if(bd[curx][cury][curz] == 3) return curcnt;
for (int i = 0; i < 6; i++) {
int nx = dx[i] + curx;
int ny = dy[i] + cury;
int nz = dz[i] + curz;
// 벽(1)이면 못감. 유효범위, 방문여부 확인
if (!rangecheck(nx, ny, nz) || bd[nx][ny][nz] == 1 || vis[nx][ny][nz]) continue;
vis[nx][ny][nz] = true; // 방문
qu.push({{nx,ny},{nz, curcnt+1}});
}
}
return -1;
}
void input(){ // 입력받기
// 초기화
initvis();
while(!qu.empty()) qu.pop(); // 큐 비우기
// 입력받기
char ch;
for(int i = 0; i < L; i++) { // 층
for (int j = 0; j < R; j++) { // 행
for (int k = 0; k < C; k++) { // 열
cin >> ch;
if (ch == '#') { // 벽 1
bd[i][j][k] = 1;
} else if (ch == 'S') { // 시작 위치 2
bd[i][j][k] = 2;
vis[i][j][k] = true;
qu.push({{i,j},{k,0}});
} else if (ch == 'E') { // 출구 3
bd[i][j][k] = 3;
}
}
}
}
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
while(1){
cin >> L >> R >> C; // 입력받기
if(L==0 && R ==0 && C==0) break; // 종료조건
input();
int result = bfs();
if(result < 0) cout << "Trapped!" << '\n';
else cout << "Escaped in "<<result << " minute(s)." << '\n';
}
return 0;
}
728x90
'알고리즘 > 백준' 카테고리의 다른 글
곱셈 백준 1629번 c++ (0) | 2021.12.08 |
---|---|
수 찾기 백준 1920번 c++ (0) | 2021.12.08 |
나무 자르기 백준 2805 c++ (0) | 2021.12.06 |
토마토 백준 7569 c++ (0) | 2021.12.06 |
숨바꼭질3 백준 13549 c++ (0) | 2021.12.05 |