[문제보기]
16235. 나무 재테크
16235번: 나무 재테크
부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터
www.acmicpc.net
[풀이과정]
문제를 읽고 나서 드는 생각은 다른 문제를 풀었을 때처럼 tree에 대한 정보를 그냥 2차원 배열로 만들면 안되고
vector 형식으로 격자판을 만들어야겠다고 생각했다. 왜냐하면 하나의 칸에 나무가 여러 개가 있을 수 있다고
제시되어 있기 때문에 vector 형태가 생각이 났다.
필자가 사용한 변수들은 현재 땅의 양분들이 저장되어 있는 map[][], 겨울이 왔을 때 더해줄 양분의 정보를 가지고
있는 eat_add[][], 그리고 위에서 말했던 나무들의 나이 정보를 가지고 있는 vector tree[][], 그리고 가을이 되었을 때,
번식 위치에 대한 정보를 가지고 있는 movdir[8] 이렇게 4가지 변수를 중점으로 문제를 풀었다.
0. vec_sort()
봄 연산에서 어린 나무부터 양분을 섭취한다고 제시되어 있기 때문에 각 땅에 저장한 나무들의 정보들을 오름차순으로
정렬을 시켜준 후 봄/여름 연산을 진행하였다.
1. 봄 & 여름(spring_summer())
-> 주석에 쓰여있다시피 봄이 되면 어린 나무부터 양분을 섭취하고, 자기 나이만큼 먹게 되면 나이가 1 증가하고,
충분한 양분을 섭취하지 못한 나무들은 죽게 된다. 죽은 나무들은 그 땅에 양분이 되는데 (나이/2)만큼 된다.
나무가 양분을 섭취하고 죽은 나무가 땅의 양분이 되는 연산은 한꺼번에 처리하는 것이 더 괜찮다고 생각을 하여 필자는
봄과 여름의 연산을 한 함수 안에서 했다.
이중 for문을 통해 각 땅마다 확인을 하고 각 땅에 있는 나무만큼 양분을 섭취할 수 있게 했다. 양분을 섭취하는 도중
충분히 양분을 섭취하지 못한 나무가 나오면 break를 하여 그 뒤의 나무들을 죽은 나무로 취급하여 여름 연산을
진행하였다. (오름차순으로 정렬을 했기 때문에 그 뒤의 나무들은 확인할 필요가 없다)
그리고 vector temp 변수를 하나 만들어 양분을 충분히 섭취한 나무들의 나이 정보를 저장하고 여름 연산이 끝난 후
clear 된 vector tree[][]에 저장해주고, map[][] 배열에 만들어진 양분을 더해준다.
2. 가을(fall())
-> 번식에 대한 연산이다. 나이가 5의 배수인 나무들이 번식을 하게 되는데 번식은 인접한 8칸에 나이가 1인 나무들로
번식이 된다.
이중 for문을 통해 각 땅의 나이가 5의 배수인 나무들에 대해 번식을 진행해준다.
인접한 8칸에 대한 연산은 movdir[8] 배열을 사용하여 진행했다.
3. 겨울(winter())
-> 로봇이 돌아다니면서 양분을 추가하는 연산
구현하기 제일 쉬운 부분으로 이전에 입력값을 저장했던 eat_add[][] 배열을 map[][] 배열에 더해주었다.
[소스코드]
//나무 재테크
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n, m, k;
int map[11][11];
int eat_add[11][11];
vector<int> tree[11][11];
pair<int, int> movdir[8] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
{0, 1}, {1, -1}, {1, 0}, {1, 1}};
void vec_sort(){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(tree[i][j].size() == 0) continue;
sort(tree[i][j].begin(), tree[i][j].end());
}
}
}
void spring_summer(){
//나이만큼 양분 먹고 나이 1증가(어린 나무부터)
//양분을 못 먹으면 죽음
//죽은 나무는 양분으로
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(tree[i][j].size() == 0) continue;
int save = 0;
int k;
vector<int> temp;
//봄 연산
for(k=0; k<tree[i][j].size(); k++){
if(tree[i][j][k] <= map[i][j]){
map[i][j] -= tree[i][j][k];
temp.push_back(tree[i][j][k]+1);
continue;
}
break;
}
//여름 연산
for(int die = k; die<tree[i][j].size(); die++){
save += (tree[i][j][die]/2);
}
tree[i][j].clear();
for(int l = 0; l<temp.size(); l++){
tree[i][j].push_back(temp[l]);
}
map[i][j] += save;
}
}
}
void fall(){
//나이가 5의 배수 나무들 번식
//인접한 8칸에 나무 증가
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
for(int k=0; k<tree[i][j].size(); k++){
if(tree[i][j][k] % 5 != 0) continue;
for(int add = 0; add <8; add++){
int nexty = i + movdir[add].first;
int nextx = j + movdir[add].second;
if(nexty <= 0 || n < nexty || nextx <= 0 || n < nextx)
continue;
tree[nexty][nextx].push_back(1);
}
}
}
}
}
void winter(){
//로봇이 돌아다니면서 양분 추가
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
map[i][j] += eat_add[i][j];
}
}
}
int main(){
cin >> n >> m >> k;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
cin >> eat_add[i][j];
map[i][j] = 5;
}
}
for(int i=0; i<m; i++){
int x, y, age;
cin >> x >> y >> age;
tree[x][y].push_back(age);
}
while(k--){
vec_sort();
spring_summer();
fall();
winter();
}
int cnt = 0;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(!tree[i][j].empty())
cnt += tree[i][j].size();
}
}
cout << cnt;
}
[해결 과정 중 실수한 부분]
'알고리즘 스터디 > Beakjoon' 카테고리의 다른 글
[백준 1932][C++] 정수 삼각형 (Silver 1) (0) | 2020.08.29 |
---|---|
[백준 2579][C++] 계단 오르기 (Silver 3) (0) | 2020.08.28 |
[백준 15685][C++] 드래곤 커브 (Gold 4) (0) | 2020.08.25 |
[백준 17144][C++] 미세먼지 안녕! (Gold 5) (0) | 2020.08.25 |
[백준 16236][C++] 아기 상어 (Gold5) (0) | 2020.08.24 |