[BOJ] 16235 : 나무 재테크

16235 : 나무 재테크

풀이

시뮬레이션

삼성SW기출문제.

나무를 심어놓고 나무가 양분을 먹고 못먹으면 죽고, 땅에 다시 양분을 넣어주고…를 반복해서

K년이 지난후에 나무가 몇그루가 되었을까?를 시뮬레이션 하는 문제이다.

가을에 나무가 번식을 할때가 까다로웠는데, 왜냐하면 봄에 양분을 먹는 순서는 나이가 어린순서인데,

번식을 하면 나이가 1인 나무들이 생겨나기 때문이다.

예전에는 우선순위큐를 이용해서 이문제를 해결했었다.(800ms)

이번에는 deque를 이용해서 해결했다(100ms)

0ms로 푸신분들도 있는것으로 보아 훨씬 효율적인 방법이 또 있나보다.

코드

#include <iostream>
#include <queue>
#include <deque>
#include <vector>
#include <cstring>
#include <functional>
using namespace std;

//현재 칸의 양분 정보, 초기값 5
int remain[10][10];
//각 칸에 추가될 양분의 양
int energy[10][10];
//각 좌표마다의 나무 정보
deque<int> q[10][10];
//죽은 나무 임시저장
vector<int> death[10][10];
//8방향
const int dx[] = { -1,-1,-1,0,0,1,1,1 };
const int dy[] = { -1,0,1,-1,1,-1,0,1 };

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    //나무재테크, K년이 지난후 살아남은 나무의 수
    int n, m, k;
    cin >> n >> m >> k;
    //추가될 양분정보, 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> energy[i][j];
            remain[i][j] = 5;
        }
    }
    //나무정보
    int x, y, year;
    for (int i = 0; i < m; i++) {
        cin >> x >> y >> year;
        q[x-1][y-1].push_back(year);
    }
    
    while (k--) {
        //봄 : 나이만큼 양분먹고 나이1증가. 어린 나무부터 양분먹음
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int num = q[i][j].size();
                for (int k = 0; k < num; k++) {
                    if (q[i][j].front() <= remain[i][j]) {
                        remain[i][j] -= q[i][j].front();
                        q[i][j].push_back(q[i][j].front() + 1);
                        q[i][j].pop_front();
                    }
                    else {
                        death[i][j].push_back(q[i][j].front());
                        q[i][j].pop_front();
                    }
                }
            }
        }
        //여름:죽은나무 양분
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < death[i][j].size(); k++) {
                    remain[i][j] += death[i][j][k] / 2;
                }
                death[i][j].clear();
            }
        }
        //가을:나무번식(5배수 나이인 나무가 있으면 인접8칸에 나이1나무 생김)
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int num = q[i][j].size();
                for (int k = 0; k < num; k++) {
                    if (q[i][j].front() % 5 == 0) {
                        //번식
                        for (int dir = 0; dir < 8; dir++) {
                            int nx = i + dx[dir];
                            int ny = j + dy[dir];
                            if (nx >= 0 && nx < n&&ny >= 0 && ny < n) {
                                q[nx][ny].push_front(1);
                            }
                        }
                        q[i][j].push_back(q[i][j].front());
                        q[i][j].pop_front();
                    }
                    else {
                        q[i][j].push_back(q[i][j].front());
                        q[i][j].pop_front();
                    }
                }
            }
        }

        //겨울:양분추가
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                remain[i][j] += energy[i][j];
            }
        }
    }
    //살아있는 나무 계산
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            ans += q[i][j].size();
        }
    }
    cout << ans;
    return 0;
}
Written on April 12, 2019