https://www.acmicpc.net/problem/7569
<토마토>
이 문제는 한 토마토가 익은 상태라면, 다음 날에는 그 토마토의 앞, 뒤, 왼쪽, 오른쪽, 위, 아래의 토마토가 익게 되는데,
이 때 상자에 있는 모든 토마토가 익는 데에 최소 몇 일이 걸리는 지 계산해주어 출력해주는 문제이다.
모든 토마토를 익게 할 수 없을 시에는 -1을 출력해주고, 처음부터 모든 토마토가 익어있는 경우엔 0을 출력해주면 된다.
하나 하나가 자신의 전후좌우를 전염시켜나가는 문제들과 유사한데, 조금 다른 점은 한 층의 배열이 아닌
여러 층으로 이루어져 상, 하까지 전염시켜주어야 하는 것이다.
3차원 배열을 자주 사용해보진 않았지만, 예를들어 2 x 3 배열이 2개 있다는 것은 2 x 2 x 3으로 생각하면 되므로
int arr[2][3] 을 int arr[2][2][3]으로만 선언해주면 된다고 생각하고 문제를 풀었다.
문제는 다른 높이가 없는 토마토 문제처럼 BFS 알고리즘을 이용하여 풀었다.
처음 익은 토마토(1)와 익지 않은 토마토(0), 빈 상자(-1)를 입력 받게 되는데, 익은 토마토를 입력 받았을 때
queue에 넣어주는 형태로 했다.
물론 queue를 하나로 만들어 queue<pair<int, pair<int, int> > > q 형태로 선언되도 되겠지만,
좀 편하게 코딩하고 싶어서 높이 큐와 좌표 큐를 따로 두어 넣었다.
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <queue> #define SIZE 101 using namespace std; enum TOMATO_RIPE { N_RIPE, RIPE }; int n, m, h; int tomato[SIZE][SIZE][SIZE]; bool IsRipe[SIZE][SIZE][SIZE]; int total_tomato = 0; // 익지 않은 토마토 개수 int harr[6] = { 0, 0, 0, 0, 1, -1 }; int xarr[6] = { 1, -1, 0, 0, 0, 0 }; int yarr[6] = { 0, 0, 1, -1, 0, 0 }; queue<int> qH; // 높이 큐 queue<pair<int ,int> > qNM; // 좌표 큐 bool InMap(int _h, int _n, int _m) { return (0 <= _h && _h < h && 0 <= _n && _n < n && 0 <= _m && _m < m); } int solution() { int iDay = 0; int iTomato = 0; bool flag = false; while (!qH.empty()) { int qsize = qH.size(); for (int i = 0; i < qsize; i++) { int cur_h = qH.front(); int cur_x = qNM.front().first; int cur_y = qNM.front().second; qH.pop(); qNM.pop(); for (int j = 0; j < 6; j++) { int next_h = cur_h + harr[j]; int next_x = cur_x + xarr[j]; int next_y = cur_y + yarr[j]; // 토마토 상자 밖인 경우 if (!InMap(next_h, next_x, next_y)) continue; // 익은 토마토인 경우 if (IsRipe[next_h][next_x][next_y]) continue; // 토마토가 아닌, 빈 상자인 경우 if (tomato[next_h][next_x][next_y] == -1) continue; // 익었다는 표시 IsRipe[next_h][next_x][next_y] = 1; // 큐에 넣어주기 qH.push(next_h); qNM.push({ next_x, next_y }); // 익은 토마토 개수 증가 iTomato++; // 날짜 증가 플래그 flag = true; } } // 토마토가 익은 경우에만 날짜 증가 if (flag) { iDay++; flag = false; } } // 전부 익었다면 if(iTomato == total_tomato) return iDay; // 같지 않다면 일부가 익지 못했으므로 -1 리턴 else return -1; } int main() { memset(IsRipe, false, sizeof(IsRipe)); // m : 가로 n : 세로 scanf("%d %d %d", &m, &n, &h); for (int i = 0; i < h; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < m; k++) { scanf("%d", &tomato[i][j][k]); if (tomato[i][j][k] == RIPE) { IsRipe[i][j][k] = true; qH.push(i); qNM.push({ j, k }); } else if (tomato[i][j][k] == N_RIPE) total_tomato++; } } } // 익지 않은 토마토 개수가 없는 경우 if (total_tomato == 0) printf("0\n"); // 익은 토마토가 한 개도 없는 경우 else if (qH.size() == 0) printf("-1\n"); else printf("%d\n", solution()); return 0; }
ps. 계속 틀려 반례를 찾지 못해 백준 질문 게시판에 올렸는데, 다른 고수님이 내 코드에서 가로, 세로, 높이 순으로 입력이 들어오는 것을
세로, 가로, 높이로 받아오고 있다는 걸 발견하고 알려주셨다. 내가 짠 코드를 다른 사람이 더 잘 분석하다니.. 더 꼼꼼하고 치밀하게 봐야겠다.
'알고리즘 > 백준 문제풀기' 카테고리의 다른 글
BOJ 백준 1753 최단경로 (0) | 2018.12.11 |
---|---|
BOJ 백준 2644 촌수계산 (0) | 2018.12.10 |
BOJ 백준 1068 트리 (0) | 2018.12.08 |
BOJ 백준 9461 파도반 수열 (0) | 2018.11.21 |
BOJ 백준 12100 2048 (Easy) (0) | 2018.11.21 |