본문 바로가기
백준

[백준] code.plus(시뮬레이션과 구현,JAVA)16235번, 나무 재테크

by 열정적인 이찬형 2022. 8. 6.

문제 링크

 

16235번: 나무 재테크

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터

www.acmicpc.net


주의사항

  • JAVA를 사용하여 프로그램을 사용하였습니다.
  • 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{ 	
	public static void main(String[] args){
    }
}

문제 설명


접근 방법

 

이 문제에 핵심은

 

1. 나무가 K년이 지난 후에 살아남은 나무의 수를 결과로 출력합니다.

2. 봄, 여름, 가을, 겨울에 맞게 나무에 대하여 성장 및 번식 등을 진행합니다.

3. 땅에는 기본적으로 5의 양분을 가지고 있습니다.

4. 나무가 번식할 때에는 인접한 8칸에 번식이 진행됩니다.

 

알고리즘 진행 순서.

 

1. 입력되는 정보들을 저장합니다.

 

2. K년 동안 봄, 여름, 가을, 겨울이 지나면서 나무 관련 정보들을 변경합니다.

 

3. K년 이후에 땅에 살아남은 나무의 수를 결과로 출력합니다.

 

 

나무는 땅에 있는 양분을 자신의 나이만큼 흡수합니다.

동일한 칸에 여러 나무가 존재할 때 나이가 낮은 나무가 먼저 흡수합니다.

양분을 나이에 맞게 흡수하지 못하는 나무들은 모두 죽습니다.

 

여름

 

봄에 죽은 나무들에 양분 값(나이/2)을 땅에 추가합니다.

 

가을

 

현재 땅에 있는 나무의 나이가 5의 배수일 때 인접한 8칸에 나이가 1인 나무들로 번식을 진행합니다.

 

겨울

 

땅에 돌아다니면서 미리 입력된 양분들을 추가합니다.

 

 

 

예제입력 3.

 

1. 입력되는 정보들을 저장합니다.

 

N : 5

M : 2

K : 1

5 5 5 5 5
5(나무O) 5 5 5 5
5 5(나무O) 5 5 5
5 5 5 5 5
5 5 5 5 5

겨울에 추가될 양분의 양

2 3 2 3 2
2 3 2 3 2
2 3 2 3 2
2 3 2 3 2
2 3 2 3 2

나무 : (2, 1, 3), (3, 2, 3)

 

2. K년 동안 봄, 여름, 가을, 겨울이 지나면서 나무 관련 정보들을 변경합니다.

 

5 5 5 5 5
2(나무O) 5 5 5 5
5 2(나무O) 5 5 5
5 5 5 5 5
5 5 5 5 5

 

여름

 

죽은 나무가 존재하지 않기 때문에 양분 흡수는 진행되지 않습니다.

 

가을

 

나무 : (2, 1, 4), (3, 2, 4)

5의 배수의 나무가 존재하지 않기 때문에 번식은 진행되지 않습니다. 

 

겨울

 

미리 입력된 양분 더하기!

7 8 7 8 7
4(나무O) 8 7 8 7
7 5(나무O) 7 8 7
7 8 7 8 7
7 8 7 8 7

3. K년 이후에 땅에 살아남은 나무의 수를 결과로 출력합니다.

 

나무 : (2, 1, 4), (3, 2, 4)

 

살아남은 나무의 개수 2를 결과로 출력합니다.

 

  • BufferedReader를 사용하여 입력 값을 받았습니다.
  • StringTokenizer를 이용하여 입력된 정보에 대하여 나누었습니다.
  • K년 동안 spring, summer, fall, winter를 순차적으로 실행하여 시뮬레이션을 진행합니다.
  • K년 이후 현재 살아있는 나무의 개수를 BufferedWriter 저장하였습니다.
  • BufferedWriter에 저장된 결과값을 출력하였습니다.
  • spring함수는 봄에 나무들이 양분들을 흡수합니다.
  • summer함수는 봄에 죽은 나무들에 양분들을 땅에 흡수하도록 합니다.
  • fall함수에서 나무의 나이가 5의 배수인 인접 칸에 나이가 1인 나무들로 번식을 합니다.
  • winter함수에서 미리 입력된 양분들을 흡수하도록 합니다.
  • inGraden함수는 fall함수에서 인접한 칸 이동시 땅 범위에 존재하는지 확인하는 함수입니다.

 

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

public class Main {
    //나무 관련 정보 클래스
    static class tree implements Comparable<tree>{
        int x, y, value;
        public tree(int x, int y, int value) {
            this.x = x;
            this.y = y;
            this.value = value;
        }
        //정렬할 때 사용할 Comprable
        @Override
        public int compareTo(tree o) {
            return this.value - o.value;
        }
    }
    static int N,M,K;
    static int[] dx = {-1, 0, 1, -1, 1, -1, 0, 1};	//인접한 칸 x변경값
    static int[] dy = {-1, -1, -1, 0, 0, 1, 1, 1};	//인접한 칸 y변경값
    static int[][] garden, nourishment;	//양분 정보, 양분 추가 정보 저장 배열
    static ArrayList<tree> deadTrees = new ArrayList<>();
    static Queue<tree> trees = new LinkedList<>();
    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());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        garden = new int[N][N];
        nourishment = new int[N][N];
        //입력되는 추가 양분에 대한 정보를 저장
        for(int i=0;i<N;i++){
            st = new StringTokenizer(br.readLine()," ");
            for(int j=0;j<N;j++){
                nourishment[i][j] = Integer.parseInt(st.nextToken());
                garden[i][j] = 5;
            }
        }
        //나무의 정보 저장
        for(int i=0;i<M;i++){
            st = new StringTokenizer(br.readLine(), " ");
            int tempY = Integer.parseInt(st.nextToken())-1;
            int tempX = Integer.parseInt(st.nextToken())-1;
            int tempValue = Integer.parseInt(st.nextToken());
            trees.add(new tree(tempX,tempY,tempValue));
        }
        Collections.sort((List<tree>) trees);	//나무 나이 기준 오름차순 정렬
        
        //K년도 진행
        for(int i=0;i<K;i++){
            spring();
            summer();
            fall();
            winter();

            if(trees.size()==0)	//더 이상 나무가 존재하지 않을 때
                break;
        }
        bw.write(trees.size() + "");
        bw.flush();
        bw.close();
        br.close();
    }
    //봄
    static void spring(){
        int size = trees.size();
        //영양분 흡수중!
        for(int i=0;i<size;i++){
            tree temp = trees.poll();
            if(garden[temp.y][temp.x] - temp.value >= 0){
                garden[temp.y][temp.x] -= temp.value;
                trees.add(new tree(temp.x, temp.y, temp.value+1));
            }else
                deadTrees.add(temp);	//죽은 나무 추가
        }
    }
    //여름
    static void summer(){
        //죽은 나무의 대한 양분들 흡수중!
        for(int i=0;i<deadTrees.size();i++){
            tree temp = deadTrees.get(i);
            garden[temp.y][temp.x] += temp.value/2;
        }
        deadTrees.clear();
    }
    //가을
    static void fall(){
        //5의 배수인 나무들 기준 인접한 칸 번식중!
        Queue<tree> newTrees = new LinkedList<>();
        for(tree cur : trees){
            for(int i=0;i<8;i++){
                int tempX = cur.x + dx[i];
                int tempY = cur.y + dy[i];
                if(cur.value % 5 == 0 && inGarden(tempX, tempY))
                    newTrees.add(new tree(tempX,tempY,1));
            }
        }
        newTrees.addAll(trees);
        trees = newTrees;
    }
    //겨울
    static void winter(){
        //미리 입력된 양분 추가중!
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++)
                garden[i][j] += nourishment[i][j];
        }
    }
    //인접한 칸 이동시 범위 안에 존재하는지 확인하는 함수
    static boolean inGarden(int x, int y){
        if(x>=0 && y>=0 && x<N && y<N)
            return true;
        return false;
    }
}
 

 

댓글