본문 바로가기

Algorithm/문제

[백준 / JAVA] 16235. 나무 재테크 (G3)

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

(언제 고쳐줘요...)

 

개인적으로 가독성이 안 좋은 문제라고 생각한다. 코드를 다 짜고 틀려서 확인해보니 모든 땅 최초 양분이 5라는 조건이 문제 맨 위에 있더라...제발 문제 컨셉 적는 공간과 조건 적는 공간은 분리해줬으면 한다.

그와 별개로 문제 자체는 PriorityQueue로 2차원 배열을 만들어서 나무 나이만 집어넣어도 가볍게 풀 수 있다. 봄과 여름 함수를 따로 구현하면 봄에 죽은 나무 리스트를 여름한테 넘겨줘야 하는 문제가 발생는데, 봄을 두 과정으로 쪼개고 중간에 여름을 끼워넣어 한번에 구현했다. 원래 메소드는 구현한 최신순으로 배치하는데 이번엔 문제 컨셉에 맞게 계절 순으로 배치해봤다.

 

시간이

 

import java.util.*;
import java.io.*;

public class Main {
	static BufferedReader br;
	static StringTokenizer st;
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		br = new BufferedReader(new InputStreamReader(System.in));
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		foodMap = new int[N][N];
		foodAddMap = new int[N][N];
		treeQMap = new PriorityQueue[N][N];
		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < N; j++) {
				int food = Integer.parseInt(st.nextToken());
				foodMap[i][j] = 5;
				foodAddMap[i][j] = food;
				treeQMap[i][j] = new PriorityQueue<>();
			}
		}
		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			treeQMap[Integer.parseInt(st.nextToken()) - 1][Integer.parseInt(st.nextToken()) - 1]
					.add(Integer.parseInt(st.nextToken()));
		}
		for (int i = 0; i < k; i++)
			grow();
		System.out.println(countTree());
	}

	static int N, foodMap[][], foodAddMap[][], dr[] = { -1, -1, -1, 0, 0, 1, 1, 1, },
			dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
	static PriorityQueue<Integer> treeQMap[][];

	static int countTree() {
		int count = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				count += treeQMap[i][j].size();
			}
		}
		return count;
	}

	static void grow() {
		springAndSummer();
		fall();
		winter();
	}

	static void springAndSummer() {
		Deque<Integer> aliveTreeQ = new ArrayDeque<>();
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				while (!treeQMap[i][j].isEmpty()) { // spring - 1
					int curTree = treeQMap[i][j].poll();
					if (foodMap[i][j] >= curTree) {
						aliveTreeQ.add(curTree + 1);
						foodMap[i][j] -= curTree;
					} else {
						treeQMap[i][j].add(curTree);
						break;
					}
				}
				while (!treeQMap[i][j].isEmpty()) { // summer
					int deadTree = treeQMap[i][j].poll();
					foodMap[i][j] += deadTree / 2;
				}
				while (!aliveTreeQ.isEmpty()) // spring - 2
					treeQMap[i][j].add(aliveTreeQ.poll());
			}
		}
	}

	static void fall() {
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++) {
				int count = 0; // 나이 5의 배수 나무
				for (int tree : treeQMap[i][j]) {
					if (tree % 5 == 0)
						count++;
				}
				for (int d = 0; d < dr.length; d++) {
					int nr = i + dr[d];
					int nc = j + dc[d];
					if (nr < 0 || nc < 0 || nr >= N || nc >= N)
						continue;
					for (int k = 0; k < count; k++)
						treeQMap[nr][nc].add(1);
				}
			}
	}

	static void winter() {
		for (int i = 0; i < N; i++)
			for (int j = 0; j < N; j++)
				foodMap[i][j] += foodAddMap[i][j];
	}
}