백준 나무 재테크

KIMYEONGJUN·5일 전
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

첫째 줄에 N, M, K가 주어진다.
둘째 줄부터 N개의 줄에 A배열의 값이 주어진다.
r번째 줄의 c번째 값은 A[r][c]이다.
다음 M개의 줄에는 상도가 심은 나무의 정보를 나타내는 세 정수 x, y, z가 주어진다.
처음 두 개의 정수는 나무의 위치 (x, y)를 의미하고, 마지막 정수는 그 나무의 나이를 의미한다.

첫째 줄에 K년이 지난 후 살아남은 나무의 수를 출력한다.

내가 이 문제를 보고 생각해본 부분

먼저 땅 크기 N, 나무 수 M, 연도 수 K를 입력받고, 겨울에 양분 추가 배열 A와 현재 양분 상태 nutrients를 초기화한다. 
nutrients 초기값은 모든 칸에 5이다.
각 칸마다 나무 나이들을 ArrayList<Integer>로 저장한다. 
나무 위치와 나이를 받고 나서 각 리스트를 나이순으로 정렬한다.
K년 동안 매년 봄~여름~가을~겨울 단계 함수를 차례로 호출한다.
봄과 여름에서는:
나무 리스트를 나이순으로 정렬 후, 양분을 먹을 수 있으면 나이만큼 소비하고 나이를 1 증가시킨 나무만 별도 리스트에 저장한다.
양분 부족으로 죽은 나무는 양분으로 변환되므로 나이의 절반을 더해준다.
각각의 칸 나무 리스트를 생존한 나무 리스트로 교체한다.
가을에서는:
나이 5의 배수인 나무가 있으면 그 칸 주변 8방향에 나이 1인 나무를 추가한다.
새 나무는 어린 나무이므로 리스트 앞쪽에 추가하여 다음 봄에 젊은 나무부터 양분을 먹도록 한다.
겨울에는:
입력 받은 배열 A대로 각 칸에 양분을 추가해 준다.
마지막으로 남은 나무 수를 모두 합해 출력한다.

코드로 구현

package baekjoon.baekjoon_33;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

// 백준 16235번 문제
public class Main1339 {
    static int N, M, K;
    static int[][] A;          // 겨울에 추가되는 양분
    static int[][] nutrients;  // 현재 땅의 양분
    static ArrayList<Integer>[][] trees;  // 각 칸에 있는 나무 나이 리스트
    static int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};  // 8방향
    static int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 입력 받기
        String[] nmK = br.readLine().split(" ");
        N = Integer.parseInt(nmK[0]);
        M = Integer.parseInt(nmK[1]);
        K = Integer.parseInt(nmK[2]);

        A = new int[N][N];
        nutrients = new int[N][N];
        trees = new ArrayList[N][N];

        for (int i = 0; i < N; i++) {
            String[] temp = br.readLine().split(" ");
            for (int j = 0; j < N; j++) {
                A[i][j] = Integer.parseInt(temp[j]);
                nutrients[i][j] = 5;  // 초기 양분은 5
                trees[i][j] = new ArrayList<>();
            }
        }

        // 나무 초기 위치 및 나이 입력 (1-based → 0-based)
        for (int i = 0; i < M; i++) {
            String[] treeInfo = br.readLine().split(" ");
            int x = Integer.parseInt(treeInfo[0]) - 1;
            int y = Integer.parseInt(treeInfo[1]) - 1;
            int age = Integer.parseInt(treeInfo[2]);
            trees[x][y].add(age);
        }
        // 나무들을 각 칸마다 나이순 정렬
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                Collections.sort(trees[i][j]);

        // K년 반복
        for (int year = 0; year < K; year++) {
            springAndSummer();
            autumn();
            winter();
        }

        // 살아남은 나무 수 계산
        int result = 0;
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                result += trees[i][j].size();

        System.out.println(result);
        br.close();
    }

    // 봄과 여름 처리
    static void springAndSummer() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (trees[i][j].isEmpty())
                    continue;
                ArrayList<Integer> survived = new ArrayList<>();
                int deadNutrients = 0;
                Collections.sort(trees[i][j]);  // 어린 나무부터 양분 먹게 정렬
                for (int age : trees[i][j]) {
                    if (nutrients[i][j] >= age) {
                        nutrients[i][j] -= age;
                        survived.add(age + 1);
                    } else {
                        deadNutrients += age / 2;  // 죽은 나무 양분으로 전환
                    }
                }
                nutrients[i][j] += deadNutrients;
                trees[i][j] = survived;
            }
        }
    }

    // 가을 처리 - 번식
    static void autumn() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (trees[i][j].isEmpty())
                    continue;
                for (int age : trees[i][j]) {
                    if (age % 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) {
                                // 나무 번식 시 나이 1인 나무가 추가 (가장 어린 나무가 앞에 오도록 0번 인덱스에 삽입)
                                trees[nx][ny].add(0, 1);
                            }
                        }
                    }
                }
            }
        }
    }

    // 겨울 처리 - 양분 추가
    static void winter() {
        for (int i = 0; i < N; i++)
            for (int j = 0; j < N; j++)
                nutrients[i][j] += A[i][j];
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글