코딩/백준

[백준]16235번 나무 재테크 - C++

최선을 다하는 2023. 2. 10. 16:26

https://www.acmicpc.net/problem/16235

 

16235번: 나무 재테크

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터

www.acmicpc.net

문제

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터 떨어진 칸의 개수, c는 가장 왼쪽으로부터 떨어진 칸의 개수이다. r과 c는 1부터 시작한다.

상도는 전자통신공학과 출신답게 땅의 양분을 조사하는 로봇 S2D2를 만들었다. S2D2는 1×1 크기의 칸에 들어있는 양분을 조사해 상도에게 전송하고, 모든 칸에 대해서 조사를 한다. 가장 처음에 양분은 모든 칸에 5만큼 들어있다.

매일 매일 넓은 땅을 보면서 뿌듯한 하루를 보내고 있던 어느 날 이런 생각이 들었다.

나무 재테크를 하자!

나무 재테크란 작은 묘목을 구매해 어느정도 키운 후 팔아서 수익을 얻는 재테크이다. 상도는 나무 재테크로 더 큰 돈을 벌기 위해 M개의 나무를 구매해 땅에 심었다. 같은 1×1 크기의 칸에 여러 개의 나무가 심어져 있을 수도 있다.

이 나무는 사계절을 보내며, 아래와 같은 과정을 반복한다.

봄에는 나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가한다. 각각의 나무는 나무가 있는 1×1 크기의 칸에 있는 양분만 먹을 수 있다. 하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다. 만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다.

여름에는 봄에 죽은 나무가 양분으로 변하게 된다. 각각의 죽은 나무마다 나이를 2로 나눈 값이 나무가 있던 칸에 양분으로 추가된다. 소수점 아래는 버린다.

가을에는 나무가 번식한다. 번식하는 나무는 나이가 5의 배수이어야 하며, 인접한 8개의 칸에 나이가 1인 나무가 생긴다. 어떤 칸 (r, c)와 인접한 칸은 (r-1, c-1), (r-1, c), (r-1, c+1), (r, c-1), (r, c+1), (r+1, c-1), (r+1, c), (r+1, c+1) 이다. 상도의 땅을 벗어나는 칸에는 나무가 생기지 않는다.

겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가한다. 각 칸에 추가되는 양분의 양은 A[r][c]이고, 입력으로 주어진다.

K년이 지난 후 상도의 땅에 살아있는 나무의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N, M, K가 주어진다.

둘째 줄부터 N개의 줄에 A배열의 값이 주어진다. r번째 줄의 c번째 값은 A[r][c]이다.

다음 M개의 줄에는 상도가 심은 나무의 정보를 나타내는 세 정수 x, y, z가 주어진다. 처음 두 개의 정수는 나무의 위치 (x, y)를 의미하고, 마지막 정수는 그 나무의 나이를 의미한다.

출력

첫째 줄에 K년이 지난 후 살아남은 나무의 수를 출력한다.


글이 굉장히 길지만 계절별로 작업 처리하는 것을 반복해야 한다는 것을 굉장히 친절하게 설명해 준 것이다.

문제에서 주어진 값 외에

int soil [11][11] => 해당 칸의 양분 수이다.

vector <int> tree [11][11] => tree [i][j] 번째 벡터는 해당 자리의 나무를 나타낸다.

 

같은 칸에 여러 개의 나무가 있다면 나이가 적은 나무부터 양분을 소모하기 때문에 새로운 나무가 tree [i][j]에 추가될 때마다 정렬해 준다.

 

봄에는 tree 배열을 순회하면서 나무를 탐색한다. 나무의 나이보다 soil [i][j]이 같거나 많으면 tree의 나이가 1 증가하고 soil이 감소한다. 만약 양분이 나무의 나이보다 적으면 tree를 큐에 추가하여 여름에 양분이 되도록 한다.

 

여름에는 봄에 추가된 큐의 원소들로 soil [i][j]의 값을 증가시킨다.

 

가을에는 tree를 순회하여 나무의 나이가 5의 배수이면 주위 8칸 vector에 새로운 나무를 추가해 준다. 이때 새로 추가되는 나무의 나이가 1이므로 맨 앞에 삽입하도록 한다.

 

겨울에는 soil [i][j]에 A [i][j]를 더한다.

 


알고리즘이 어렵다기보다 자료구조를 잘 활용해야하는 문제인 것 같다. 같은 자리에 여러가지 바뀔 수 있는 값이 있을 수 있으므로 2차원 tree 벡터를 설정하였다. 가을에 번식을 한 나무의 나이는 1이기 때문에 그 즉시 나무 리스트에 추가해도 영향이 없어 바로 추가하였다. 다만  이번에 iterator를 활용하여 tree[i][j]를 순회 한것과 맨 앞에 삽입하기 위해 v.insert(v.begin(),값) 을 한것을 새로 배웠다. 새로 배운 내용은 구글링을 했지만 그래도 처음 구상한 방법으로 첫 제출이 성공을 하여 뿌듯했다! 

'코딩 > 백준' 카테고리의 다른 글

[백준] 15683번 감시 - C++  (0) 2023.02.12
[백준]6593번 상범 빌딩  (0) 2023.02.11
[백준]9205번 맥주 마시면서 걸어가기 - C++  (2) 2023.02.09
[백준]17135번 캐슬 디펜스 - C++  (0) 2023.02.08
[백준] 1563번 - 개근상  (0) 2023.02.06