문제 접근
- tuple을 쓰자.
3차원 공간 정보를 저장해야 된다. 구조체를 써도 되기는 하지만, 그냥 속 편하게 튜플을 썼다. - 익은 토마토를 방문한 토마토로 생각하자.
별도로 visited 배열을 만들지 않고, 익은 토마토를 방문한 토마토로 생각했다. - 배열을 굳이 동적 할당하려고 하지 말자.
기본 입력 값과 메모리 제한이 넉넉하다면, 그냥 최대 크기로 만들고, 일부만 사용하고자 했다.
https://www.acmicpc.net/problem/7569
7569번: 토마토
첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100,
www.acmicpc.net
문제 코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;
int main(void)
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int M, N, H, remain_tomato = 0, ans = -1;
int box[102][102][102];
int dwidth[6] = { 0, 0, -1, 1, 0, 0 };
int dlength[6] = { 0, 0, 0, 0, -1, 1 };
int dheight[6] = { 1, -1, 0, 0, 0, 0 };
queue<tuple<int, int, int, int>> ripe_tomato_about_time;
cin >> M >> N >> H;
for (int height = 1; height <= H; ++height)
{
for (int length = 1; length <= N; ++length)
{
for (int width = 1; width <= M; ++width)
{
cin >> box[width][length][height];
if (box[width][length][height] == 0)
++remain_tomato;
else if (box[width][length][height] == 1)
ripe_tomato_about_time.push(make_tuple(0, width, length, height));
}
}
}
while (!ripe_tomato_about_time.empty())
{
tuple<int, int, int, int> current_tomato = ripe_tomato_about_time.front();
ripe_tomato_about_time.pop();
if (ans < get<0>(current_tomato))
ans = get<0>(current_tomato);
for (int direction_idx = 0; direction_idx < 6; ++direction_idx)
{
if (get<1>(current_tomato) + dwidth[direction_idx] < 1 || get<1>(current_tomato) + dwidth[direction_idx] > M || get<2>(current_tomato) + dlength[direction_idx] < 1 || get<2>(current_tomato) + dlength[direction_idx] > N || get<3>(current_tomato) + dheight[direction_idx] < 1 || get<3>(current_tomato) + dheight[direction_idx] > H)
continue;
int next_tomato_state = box[get<1>(current_tomato) + dwidth[direction_idx]][get<2>(current_tomato) + dlength[direction_idx]][get<3>(current_tomato) + dheight[direction_idx]];
if (next_tomato_state != 0)
continue;
box[get<1>(current_tomato) + dwidth[direction_idx]][get<2>(current_tomato) + dlength[direction_idx]][get<3>(current_tomato) + dheight[direction_idx]] = 1;
ripe_tomato_about_time.push(make_tuple(get<0>(current_tomato) + 1, get<1>(current_tomato) + dwidth[direction_idx], get<2>(current_tomato) + dlength[direction_idx], get<3>(current_tomato) + dheight[direction_idx]));
--remain_tomato;
}
}
if (remain_tomato == 0)
cout << ans << '\n';
else
cout << "-1\n";
return 0;
}
느낀 점
오늘도 삽질을 했다. OutOfBounds가 발생해서 box 배열을 봤는데 이상이 없었다. 맞왜틀.. 맞왜틀.. 거리면서 계속 보고 있는데 갑자기 눈에 direction 배열이 7까지 도는 게 들어왔다. 설마 싶어서 6으로 수정하니 바로 AC 받더라..
분명 로컬에서는 잘 돌아가서 box 배열의 크기 문제라고 생각했는데, 고정된 direction 배열을 잘못 참조해서 문제가 발생한 거였다. 근데 왜 로컬에서는 문제가 안 생겼지..? 예제 외에도 이것저것 해봤는데.. 아마 height는 깊게 확인을 안 해서 direction이 범위를 벗어난 인덱스를 참조할 때까지는 돌지 않았나 보다.
어제, 오늘 삽질을 많이 한다. 그래도 삽질하는 속도가 점점 빨라지고 있어서 불행 중 다행인 것 같다. (다행이겠지..?)
- 맞왜틀이라는 건 없다.
틀리니까 틀리다고 나오는 것. 계속 고민해 보고, 정말 모르겠으면 질문을 하자. - Bound 조건을 잘 확인하자.
좌표가 1~100까지인 배열을 좌표 별로 전후 1 칸씩 확인해야 하면, 0~101의 범위를 확인하게 된다. 배열의 bound를 넘어가지 않도록 잘 처리하자.
변수 명을 직관적으로 만들어보겠다는 부분, 생각대로 잘 이행하고 있다. 그런데 문득 '직관적으로 만든 변수 명이 오히려 가독성을 떨어뜨리지는 않을까?'라는 의문이 든다. 이번 코드를 보면 충분히 이런 생각이 들만한데, 시간이 되면 로버트 C. 마틴의 저서를 보며 좋은 코드에 대해 다시 한번 깊게 고민해 보고, 코딩 스타일을 개선해 보자.
'개발 > 알고리즘' 카테고리의 다른 글
백준 9019번 : DSLR (2) | 2023.02.18 |
---|---|
백준 2178번 : 미로 탐색 (0) | 2023.02.17 |
백준 1260번 : DFS와 BFS (0) | 2023.02.16 |
백준 18111번 : 마인크래프트 (0) | 2023.02.15 |
백준 2805번 : 나무 자르기 (0) | 2023.02.15 |