[ 백준 ] 16235 / 나무 재테크

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
35/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 16235 / 나무 재테크
 *
 * Kind :: Simulation
 *
 * Insight
 * - 시간제한이 0.3초? 근데 max(N)=10 이다
 *   메모리 제한은 512MB 다
 *   N 이 정말 작고 메모리는 넉넉하니
 *   공간을 최대한 활용해서 시간을 최적화하자
 *   + 여느 구현 문제와 마찬가지로
 *     문제에서 시키는 것을 빠짐없이 잘 만들어야 한다
 *     # 봄
 *       나이가 어린 나무부터 양분을 먹는다고 하니
 *       나무를 나이 오름차순대로 정렬되어 있으면 좋을 듯 하다
 *     # 여름
 *       양분을 못 먹은 나무는 죽고 양분이 된다
 *       봄에서 양분을 먹은 나무와 그렇지 않은 나무를 구분해서
 *       다루어주면 될 듯 하다
 *     # 가을
 *       나이가 5의 배수인 나무는 번식한다
 *       나이와 상관없이 인접한 8칸에 나이가 1인 나무가 생기므로
 *       번식하는 나무의 개수만 매년마다 추적해주자
 *     # 겨울
 *       A[i][j] 를 각 땅에 더해주자
 *       -> 매년 각 땅에 더해지는 양분의 양 정보를 담고 있는 2차원 배열 필요
 *          => (int) A[i][j]
 *          각 땅의 남은 양분 정보를 담고 있는 2차원 배열 필요
 *          => (int) R[i][j]
 *          각 땅에서 번식할 나무의 개수를 담고 있는 2차원 배열 필요
 *          => (int) P[i][j]
 *          각 땅의 나무들의 나이를 오름차순으로 저장하고 있는 3차원 배열 필요
 *          => (vector<int>) T[i][j]
 *
 * Point
 * - main 함수에 다 몽땅 구현하면
 *   가독성이 너무 떨어질 것 같으니
 *   각 계절로 구분해서 함수를 만들어주자
 *   + (봄,여름) 과 (가을,겨울) 은 동작이 달라도
 *     각 땅을 순회하면서 한번에 다루어줄 수 있을 듯 하니
 *     두 계절 함수를 하나로 합쳐주자
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <deque>
#include <algorithm>

using namespace std;

#define endl '\n'

// Set up : Global Variables
int N, M, K;
int A[10][10]; // 매년 각 땅에 추가되는 양분의 양
int R[10][10]; // 각 땅의 남은 양분의 양
int P[10][10]; // 각 땅에서 번식할 나무의 개수
deque<int> T[10][10]; // 나이 오름차순으로 정렬된 각 땅의 나무들
int dy[8] = {-1, -1, -1, 0, 0, +1, +1, +1};
int dx[8] = {-1, 0, +1, -1, +1, -1, 0, +1};

// Set up : Functions Declaration
void spring_summer();
void autumn_winter();
bool isValid(int y, int x);


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    cin >> N >> M >> K;
    for (int i=0; i<N; i++)
        for (int j=0; j<N; j++)
            cin >> A[i][j];
    for (int i=0; i<M; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        T[--x][--y].push_back(z);
    }

    // Process
    fill(&R[0][0], &R[9][9+1], 5); /* 각 땅의 양분의 양을 5로 초기화 */
    for (int i=0; i<N; i++) { /* 각 땅의 나무들을 나이 오름차순으로 정렬 */
        for (int j=0; j<N; j++) {
            sort(T[i][j].begin(), T[i][j].end());
        }
    }

    while (K--) {
        spring_summer();
        autumn_winter();
    }

    int ans = 0;
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            ans += T[i][j].size();
        }
    }

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
void spring_summer()
/* 봄, 여름 */
{
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            int s = T[i][j].size();
            bool isDried = false; /* 양분 고갈 */
            for (int k=0; k<s; k++) {
                int age = T[i][j].front();
                T[i][j].pop_front();
                /* 여름 - 양분을 못 먹은 나무들을 죽어서 그 땅의 양분이 됨 */
                if (isDried || R[i][j] < age) {
                    isDried = true;
                    R[i][j] += age/2;
                /* 봄 - 양분을 먹은 나무들은 나이가 1 증가함 */
                } else {
                    R[i][j] -= age;
                    T[i][j].push_back(age+1);
                    if ((age+1)%5 == 0) {
                        P[i][j]++;
                    }
                }
            }
        }
    }
}

void autumn_winter()
/* 가을, 겨울 */
{
    for (int i=0; i<N; i++) {
        for (int j=0; j<N; j++) {
            /* 가을 - 나이가 5의 배수인 나무들은 번식함 */
            if (P[i][j] > 0) {
                for (int k=0; k<8; k++) {
                    int ay = i + dy[k];
                    int ax = j + dx[k];
                    if (isValid(ay, ax)) {
                        T[ay][ax].insert(T[ay][ax].begin(), P[i][j], 1);
                    }
                }
            }
            P[i][j] = 0; /* 번식이 끝나면 P[i][j] 초기화 */
            R[i][j] += A[i][j]; /* 겨울 - 각 땅마다 일정량의 양분이 더해짐 */
        }
    }
}

bool isValid(int y, int x)
/* 좌표 (y,x) 가 상도의 땅 안에 있으면 true 를 반환, 밖에 있으면 false 를 반환 */
{
    return y >= 0 && y < N && x >= 0 && x < N;
}
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글