나무 재태크 : https://www.acmicpc.net/problem/16235
봄,여름,가을,겨울 순으로 필요한 값들을 갱신해주고 K만큼 반복하면 된다.
문제 풀이순서는 아래와 같다.
Queue
를 선택했다.현재 영양분 - 현재 나무 나이
가 0보다 작다면 죽은 나무 리스트에 저장하고 그렇지 않다면 trees에 현재 나무를 다시 넣어준다.나이/2
만큼 죽은 나무 좌표에 영양분을 갱신해준다.5의 배수인 나무
들과 인접한 8곳에 나이 1 나무를 Queue에 추가해주고 trees에 있는 나무의 나이순으로 정렬
한다.public class 나무재태크 {
//기준좌표로부터 순서대로 왼쪽 위, 위, 오른쪽 위, 왼쪽, 오른쪽, 왼쪽 아래, 아래, 오른쪽 아래
static int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};
static int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};
//영양분 배열
static int[][] soil;
//겨울에 추가될 영양분
static int[][] add;
//살아있는 나무 리스트
static Queue<Tree> trees;
//영양분 배열의 크기
static int N;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
soil = new int[N][N];
add = new int[N][N];
trees = new LinkedList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < N; j++) {
//초기 영양분은 5
soil[i][j] = 5;
//각 좌표에 추가 영양분
add[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine(), " ");
int x = Integer.parseInt(st.nextToken()) - 1;
int y = Integer.parseInt(st.nextToken()) - 1;
int z = Integer.parseInt(st.nextToken());
trees.offer(new Tree(x, y, z));
}
//trees에 저장된 나무 나이의 오름차순으로 정렬
Collections.sort((List<Tree>)trees);
while (K-- > 0) {
//봄,여름
springToSummer();
//가을
fall();
//겨울
winter();
}
//살아있는 나무의 개수
bw.write(String.valueOf(trees.size()));
bw.flush();
bw.close();
}
static void springToSummer() {
//영양분을 먹지 못해 죽은 나무 리스트
Queue<Tree> dieTrees = new LinkedList<>();
int treeSize = trees.size();
for (int i = 0; i < treeSize; i++) {
Tree currentTree = trees.poll();
//영양분을 먹지 못하는 나무
if (soil[currentTree.x][currentTree.y] - currentTree.age < 0) {
//죽은 나무 리스트에 저장
dieTrees.offer(currentTree);
} else {
//영양분을 먹었다면 해당 나무 나이만큼 영양분을 빼고 해당 나무 나이를 추가하고 살아있는 나무 리스트에 다시 추가
soil[currentTree.x][currentTree.y] -= currentTree.age;
currentTree.age += 1;
trees.offer(currentTree);
}
}
//죽은나무는 해당 나무의 나이/2 만큼 영양분으로 갱신
for (Tree dieTree : dieTrees) {
soil[dieTree.x][dieTree.y] += dieTree.age / 2;
}
}
static void fall() {
int treesSize = trees.size();
for (int i = 0; i < treesSize; i++) {
Tree tree = trees.poll();
//나무의 나이가 5의 배수이면 인접 8군데에 나이1인 나무 추가
if (tree.age % 5 == 0) {
for (int j = 0; j < 8; j++) {
int nx = tree.x + dx[j];
int ny = tree.y + dy[j];
if (nx >= 0 && ny >= 0 && nx < N && ny < N) {
trees.offer(new Tree(nx, ny, 1));
}
}
}
trees.offer(tree);
}
//살아있는 나무 중 나이가 적은 나무부터 영양분을 얻어야하므로 나이 오름차순으로 정렬
Collections.sort((List<Tree>)trees);
}
//영양분 추가
static void winter() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
soil[i][j] += add[i][j];
}
}
}
static class Tree implements Comparable<Tree> {
int y;
int x;
int age;
public Tree(int x, int y, int age) {
this.x = x;
this.y = y;
this.age = age;
}
@Override
public int compareTo(Tree o) {
return this.age - o.age;
}
}
}
초기 영양분이 5인것을 읽지 못해서 문제 이해하는데 오래걸렸다.. 꼼꼼히 문제를 읽자!