알고리즘 문제 풀이

백준 16235 나무 재테크(Java 자바)

superbono 2021. 4. 19. 21:04
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;
import java.util.StringTokenizer;

public class bj16235_나무재테크 {
	static int map[][];
	static int nutri[][]; // 겨울에 S2D2가 양분 줄 거 저장해둔 배열
	static int N, M, K; // N 맵 크기 M 나무 수 K 햇수
	static int x, y, z;
	static int res;
	static ArrayList<Status> tree[][];
	// 12시 방향부터 시계방향
	static class Status{
		int age;
		public Status(int age) {
			this.age = age;
		}
	}
	static int dr[] = {-1, -1, 0, 1, 1, 1, 0, -1};
	static int dc[] = {0, 1, 1, 1, 0, -1, -1, -1};
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		map = new int [N + 1][N + 1];
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				map[i][j] = 5;
			}
		}
		nutri = new int [N + 1][N + 1];
		tree = new ArrayList [N + 1][N + 1];
		
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				tree[i][j] = new ArrayList<>();
			}
		}
		// 두번째줄 map의 값
		for (int i = 1; i <= N; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 1; j <= N; j++) {
				nutri[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			x = Integer.parseInt(st.nextToken());
			y = Integer.parseInt(st.nextToken());
			z = Integer.parseInt(st.nextToken());
			
			tree[x][y].add(new Status(z));
		}
		
		Aging();
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if(tree[i][j].size() != 0) {
					res += tree[i][j].size();
				}
			}
		}
		System.out.println(res);
	}
	
	
	static void Aging() {
		for (int k = 0; k < K; k++) {
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++) {
					Collections.sort(tree[i][j], new Comparator<Status>() {
						@Override
						public int compare(Status o1, Status o2) {
							return o1.age - o2.age;
						}
					});
				}
			}
			// 봄 + 여름  봄 여름 따로 하면 시간 터짐
			// tree를 돌면서 list 사이즈가 0이 아니라면 
			int tmp [][] = new int [N + 1][N + 1];
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++) {
					if(tree[i][j].size() != 0) {
						for (int n = 0; n < tree[i][j].size(); n++) {
							// 자신의 나이 만큼 map에서 양분을 뽑아먹고 나이는 1 증가한다.
							if(map[i][j] >= tree[i][j].get(n).age) {
								map[i][j] -= tree[i][j].get(n).age;
								tree[i][j].get(n).age++;
							}else {		
								tmp[i][j] += (tree[i][j].get(n).age / 2);
								tree[i][j].remove(n);
								n--;
							}
						}
					}
				}
			}
			for (int i = 1; i < N + 1; i++) {
				for (int j = 1; j < N + 1; j++) {
					map[i][j] += tmp[i][j];
				}
			}
			// 가을
			// tree를 돌면서 list사이즈가 0이 아니라면 
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++) {
					if(tree[i][j].size() != 0) {
						for (int n = 0; n < tree[i][j].size(); n++) {
							// age % 5== 0이라면  인접한 8 칸에 나이가 1인 나무가 생긴다. 
							if(tree[i][j].get(n).age % 5 == 0) {
								for (int dir = 0; dir < 8; dir++) {
									int nx = i + dr[dir];
									int ny = j + dc[dir];
									
									if(nx < 1 || ny < 1 || nx >= N + 1  || ny >= N + 1 )
										continue;
									tree[nx][ny].add(new Status(1));
								}
							}
						}
					}
				}
			}
			// 겨울
			for (int i = 1; i <= N; i++) {
				for (int j = 1; j <= N; j++) {
					// nutri를 map에 더해준다. 
					map[i][j] += nutri[i][j];
				}
			}
		}
	}
}