1. 문제이해
M은 가로 칸의 수, N은 세로 칸의 수 N개의 줄이 H번 반복하여 입력이 주어짐
ex)
5(M), 3(N), 2(H)
H 1번
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
H 2번
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
2. 문제 분석
3차원 배열을 이용해서 토마토 상자의 크기를 구성
board[N][M][H] -> 이렇게 크기가 구성되야 함
board[2][2] 이차원 배열일 때 board[0][0]의 뜻은 0행에서 0열을 의미한다.
첫번째 세로칸에서 첫번째 가로칸을 가리킨다.
board[2][2][2] 삼차원 배열일 때 board[0][0][0]의 뜻은 0행 0열에서 0층에 있는 값을 의미한다.
3. 코드
#include<iostream>
#include<tuple>
#include<queue>
using namespace std;
int board[101][101][101];
int vis[101][101][101]; // 익어가는 토마토의 방문여부 표시
int dx[6] = { -1, 1, 0, 0, 0, 0 };
int dy[6] = { 0, 0, -1, 1, 0 ,0 };
int dz[6] = { 0, 0, 0, 0, -1, 1 };
int main(void) {
ios_base::sync_with_stdio(0);
cin.tie(0);
// 1.입력
int M, N, H; // M(열), N(행), H(높이)
cin >> M >> N >> H;
queue<tuple<int, int, int>> Q;
for (int i = 0; i < H; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < M; k++) {
cin >> board[j][k][i];
if (board[j][k][i] == 1) {
Q.push({ j,k,i });
}
else if (board[j][k][i] == 0) {
// 안익은 토마토만 -1로 바꾸고 익은토마토와 벽은 모두 0이상으로 세팅
vis[j][k][i] = -1;
}
}
}
}
// 2.로직
while (!Q.empty()) {
tuple<int, int, int> cur = Q.front();
Q.pop();
/*
tie() 사용법**
튜플로 부터 여러개의 반환값을 한번에 받아서 호출하는 tie() 쪽에서 여러개의 변수에 할당
int nx = get<0>(cur) -> curX + dx[dir];
int ny = get<1>(cur) -> curY + dy[dir];
int nz = get<2>(cur) -> curZ + dz[dir];
*/
int curX, curY, curZ;
tie(curX, curY, curZ) = cur;
// 상하좌우, 위아래 체크
for (int dir = 0; dir < 6; dir++) {
int nx = curX + dx[dir];
int ny = curY + dy[dir];
int nz = curZ + dz[dir];
// 범위체크
if (nx < 0 || nx >= N || ny < 0 || ny >= M || nz < 0 || nz >= H) continue;
// 토마토 없는 칸, 이미 익은 토마토 체크
if (vis[nx][ny][nz] >= 0) continue;
vis[nx][ny][nz] = vis[curX][curY][curZ] + 1;
Q.push({ nx,ny,nz });
}
}
// 3.결과
int ans = 0;
for (int i = 0; i < H; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < M; k++) {
if (vis[j][k][i] == -1) {
cout << -1 << "\n";
return 0;
}
// vis를 모두 방문하면서 가장 큰 최소 일수를 구함
if (vis[j][k][i] > ans) {
ans = vis[j][k][i];
}
}
}
}
// 모든 토마토가 이미 익어있으면 0을 출력함(vis에서 0보다 큰 숫자가 있어야지 최소일수가 바뀌기 때문에)
cout << ans << "\n";
return 0;
}
3차원 배열로 들어가니까 어떻게 구성을 해야할지 헷갈림
재풀이 코드
#include<iostream>
#include<queue>
#include<tuple>
using namespace std;
int board[101][101][101];
int vis[101][101][101];
int dx[6] = {-1,1,0,0,0,0}; // 행
int dy[6] = {0,0,-1,1,0,0}; // 열
int dz[6] = { 0,0,0,0,-1,1}; // 높이
int m, n, h;
int main(void) {
ios_base::sync_with_stdio(0);
cin.tie(0);
// 1.입력
cin >> m >> n >> h;
queue<tuple<int, int, int>> Q;
for (int i = 0; i < h; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
cin >> board[j][k][i];
if (board[j][k][i] == 1) {
Q.push({ j,k,i });
}
else if (board[j][k][i] == 0) {
vis[j][k][i] = -1;
}
}
}
}
// 2.로직
while (!Q.empty()) {
tuple<int, int, int> cur = Q.front();
Q.pop();
for (int dir = 0; dir < 6; dir++) {
int nx = get<0>(cur) + dx[dir];
int ny = get<1>(cur) + dy[dir];
int nz = get<2>(cur) + dz[dir];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || nz < 0 || nz >= h) continue;
if (vis[nx][ny][nz] >= 0) continue;
vis[nx][ny][nz] = vis[get<0>(cur)][get<1>(cur)][get<2>(cur)] + 1;
Q.push({ nx, ny, nz });
}
}
int ans = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
if (vis[j][k][i] == -1) {
cout << -1 << '\n'; // 토마토가 모두 익지 못하는 상황
return 0;
}
else if (vis[j][k][i] > ans) {
ans = vis[j][k][i];
}
}
}
}
cout << ans << '\n';
return 0;
}