알고리즘

bj16235(나무 제테크)-구현

쥐4 2025. 4. 22. 16:33

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

이 문제는 개극혐이다.

그냥 구현이다. 클래스를 나누고 메서드를 나누면 쉽게 풀린다.

다만, 시간이 엄청 오래걸린다.

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

public class Main {
    /**
     * 봄 => 나이만큼 양분먹음, 나이 1증가, 여러개의 나무 가능, 양분못먹으면 죽음
     * => 나이대로 정렬이 필요 특정 시점부터 여름 적용 필요
     * 여름=> 죽은 나무 양분됨. 죽은나무 나이/2가 양분으로 추가됨
     * => 봄에서 한 번에 처리
     * 가을=> 5배수 나무일 시 번식(8개)
     * => 봄에서 따로 나무 모아두기
     * => 다 처리 후 번식
     * 겨울=> 땅에 양분 추가
     * => 따로 처리
     *
     * N => N*N
     * M => 나무 갯수
     * K => 년 수
     *
     * 10 * 10 * 4
     */

    static int N, M, K;
    static int[][] foods;
    static Ground[][] grounds;
    static StringTokenizer stringTokenizer;
    static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws IOException {
        initialize();
        System.out.println(solve());
    }

    private static int solve() {
        for(int k = 0; k < K; k++){
            Queue<int[]> totalBreedTrees = new ArrayDeque<>();
            for(int y = 0; y < N; y++){
                for(int x = 0; x < N; x++){
                    Queue<int[]> breedTrees = grounds[y][x].process(grounds, N);
                    totalBreedTrees.addAll(breedTrees);
                }
            }
            grounds[0][0].breedTree(grounds, N, totalBreedTrees);

            for(int y = 0; y < N; y++){
                for(int x = 0; x < N; x++){
                    grounds[y][x].food += foods[y][x];
                }
            }
        }

        int answer = 0;
        for(int y = 0 ; y < N; y++){
            for(int x = 0; x < N; x++){
                answer += grounds[y][x].getTreeCnt();
            }
        }
        return answer;
    }

    private static void initialize() throws IOException {
        stringTokenizer = new StringTokenizer(bufferedReader.readLine());
        N = Integer.parseInt(stringTokenizer.nextToken());
        M = Integer.parseInt(stringTokenizer.nextToken());
        K = Integer.parseInt(stringTokenizer.nextToken());
        foods = new int[N][N];
        grounds = new Ground[N][N];
        for(int y = 0; y < N; y++){
            stringTokenizer = new StringTokenizer(bufferedReader.readLine());
            for(int x = 0; x < N; x++){
                grounds[y][x] = new Ground();
                grounds[y][x].food = 5;
                foods[y][x] = Integer.parseInt(stringTokenizer.nextToken());
            }
        }

        for(int i = 0; i < M; i++){
            stringTokenizer = new StringTokenizer(bufferedReader.readLine());
            int y = Integer.parseInt(stringTokenizer.nextToken())-1;
            int x = Integer.parseInt(stringTokenizer.nextToken())-1;
            grounds[y][x].trees.add(new int[]{y,x,Integer.parseInt(stringTokenizer.nextToken())});
        }
    }
}

class Ground{
    PriorityQueue<int[]> trees = new PriorityQueue<>((o1, o2) -> o1[2]-o2[2]);
    int food;

    public Queue<int[]> process(Ground[][] map, int N){
        Queue<int[]> liveTree = new ArrayDeque<>();
        Queue<int[]> breedTree = new ArrayDeque<>();
        while(true){
            if(!trees.isEmpty() && food - trees.peek()[2] >= 0){
                int[] tree = trees.poll();
                food -= tree[2];
                tree[2]++;
                liveTree.add(tree);
                if(tree[2] % 5 == 0){
                    breedTree.add(tree);
                }
                continue;
            }
            break;
        }
        plusFood();
        while(!liveTree.isEmpty()){
            trees.add(liveTree.poll());
        }
        return breedTree;
    }

    public void breedTree(Ground[][] map, int N, Queue<int[]> breedTree) {
        int[] dy = {1,0,-1,0,1,-1,1,-1};
        int[] dx = {0,1,0,-1,1,-1,-1,1};
        while(!breedTree.isEmpty()){
            int[] temp = breedTree.poll();
            for(int i = 0; i < 8; i++){
                int ny = temp[0] + dy[i];
                int nx = temp[1] + dx[i];
                if(ny < 0 || ny >= N || nx < 0 || nx >= N)continue;
                map[ny][nx].trees.add(new int[]{ny, nx, 1});
            }
        }
    }

    public void plusFood(){
        while(!trees.isEmpty()){
            int[] temp = trees.poll();
            food += temp[2] / 2;
        }
    }

    public int getTreeCnt(){
        return trees.size();
    }
}