https://www.acmicpc.net/problem/6593
6593번: 상범 빌딩
문제 당신은 상범 빌딩에 갇히고 말았다. 여기서 탈출하는 가장 빠른 길은 무엇일까? 상범 빌딩은 각 변의 길이가 1인 정육면체(단위 정육면체)로 이루어져있다. 각 정육면체는 금으로 이루어져 있어 지나갈 수 없거나, 비어있어서 지나갈 수 있게 되어있다. 당신은 각 칸에서 인접한 6개의 칸(동,서,남,북,상,하)으로 1분의 시간을 들여 이동할 수 있다. 즉, 대각선으로 이동하는 것은 불가능하다. 그리고 상범 빌딩의 바깥면도 모두 금으로 막혀있어 출구를 통해서
www.acmicpc.net
3차원 행렬을 이용한 다익스트라로 해결한 문제이다.
6개 방향으로 이동이 가능하며 #인 지점은 이동하지 못한다. 처음에 S의 위치를 큐에 삽입하여 시작점을 저장해둔다. for문을 이용하여 6개의 방향을 탐색하고 #인 지점과 S인 지점을 제외하고 모든 곳을 탐색한다. 탐색 도중 끝나는 지점인 E를 만난다면 그 지점의 탐색을 종료하고 다른 지점으로 넘어가 재탐색한다. 탐색을 진행하면서 현재 비용보다 갱신하려는 비용이 더 작으면 현재 비용을 갱신하려는 비용으로 갱신한다. 문제에서 각 층은 단 한개의 엔터만 입력이 들어온다면 그것으로 층 수를 구분한다.
#include <iostream>
#include <queue>
#define MAX 51
#define INF 100000000
using namespace std;
//좌표 정보
class Point {
public:
int x, y, z;
Point(int x, int y, int z) {
this->x = x; //층 수
this->y = y; //세로
this->z = z; //가로
}
};
int L, R, C; //층으로 L, 세로로 R, 가로로 C
char mat[MAX][MAX][MAX]; //좌표 정보
int cost[MAX][MAX][MAX]; //비용
//상,하,좌,우,up,down
int dx[] = { 1,0,-1,0,0,0 };
int dy[] = { 0,1,0,-1,0,0 };
int dz[] = { 0,0,0,0,1,-1 };
int a, b, c; //E의 위치
queue<Point> q;
//초기에 다익스트라를 위하여 모든 공간의 비용을 INF로 초기화
void setting() {
for (int i = 1; i < MAX; i++) {
for (int j = 1; j < MAX; j++) {
for (int k = 1; k < MAX; k++) {
cost[i][j][k] = INF;
}
}
}
}
void dijkstra() {
while (!q.empty()) {
int x = q.front().x;
int y = q.front().y;
int z = q.front().z;
q.pop();
if (mat[x][y][z] == 'E') { //도착 지점이면
continue; //다른 지점에서 탐색
}
for (int i = 0; i < 6; i++) { //6방향
int nx = x + dx[i];
int ny = y + dy[i];
int nz = z + dz[i];
if (1 <= nx && nx <= L && 1 <= ny && ny <= R && 1 <= nz && nz <= C && mat[nx][ny][nz] != '#' && mat[nx][ny][nz] != 'S') { //유효한 좌표 범위이고 벽이 아니고 출발지가 아니면
if (cost[nx][ny][nz] > cost[x][y][z] + 1) { //현재 비용보다 갱신하려는 비용이 더 작으면
cost[nx][ny][nz] = cost[x][y][z] + 1; //현재 비용을 갱신하려는 비용으로 갱신
q.push(Point(nx, ny, nz)); //큐에 삽입
}
}
}
}
}
int main() {
while (1) {
cin >> L >> R >> C;
if (L == 0) {
break;
}
setting();
for (int i = 1; i <= L; i++) {
bool check = false; //엔터가 제일 처음에 들어왔는지 판단하는 변수
for (int j = 1; j <= R; j++) {
for (int k = 1; k <= C; k++) {
cin >> mat[i][j][k];
if (mat[i][j][k] == 'S') {
q.push(Point(i, j, k));
cost[i][j][k] = 0;
}
else if (mat[i][1][1] == '\n') { //엔터가 제일 처음에 들어오면
check = true; //엔터가 제일 처음 들어왔다고 체크
break; //탈출
}
else if (mat[i][j][k] == 'E') {
a = i;
b = j;
c = k;
}
}
if (check == true) { //엔터가 제일 처음에 들어왔다면
break; //탈출
}
}
if (check == true) { //엔터가 제일 처음에 들어왔다면
i--; //층수를 한 층 내린다.
}
}
dijkstra();
if (cost[a][b][c] == INF) {
cout << "Trapped!\n";
}
else {
cout << "Escaped in " << cost[a][b][c] << " minute(s).\n";
}
}
}
'백준' 카테고리의 다른 글
백준1967 - 트리의 지름 (0) | 2020.03.10 |
---|---|
백준7569 - 토마토 (0) | 2020.03.05 |
백준2665 - 미로만들기 (0) | 2020.03.03 |
백준1719 - 택배 (0) | 2020.03.02 |
백준13023 - ABCDE (0) | 2020.02.28 |