티스토리 뷰
#. Problem
* The copyright in this matter is in BOJ
#. Resolution Process
1. Read and understand problem
2. Redefine the problem + abstract
3. Create solution plan (select Algorithm, Data structure)
4. Prove the plan (check performance time and usage memory)
5. Carry out the plan
6. Look back on the plan and find a way to improve it
#. Solve
구현, 시뮬레이션 문제다 !_!
조건과 동작을 먼저 잘 정리해보자.
* 가장 처음에 양분은 모든 칸에 5만큼
*. 봄에는 나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가
각각의 나무는 나무가 있는 1×1 크기의 칸에 있는 양분만 먹을 수 있다.
하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다.
만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다.
* 여름에는 봄에 죽은 나무가 양분으로 변하게 된다
각각의 죽은 나무마다 나이를 2로 나눈 값이 나무가 있던 칸에 양분으로 추가된다. 소수점 아래는 버린다.
* 가을에는 나무가 번식한다.
. 번식하는 나무는 나이가 5의 배수이어야 하며, 인접한 8개의 칸에 나이가 1인 나무가 생긴다.
어떤 칸 (r, c)와 인접한 칸은 8
상도의 땅을 벗어나는 칸에는 나무가 생기지 않는다.
* 겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가
각 칸에 추가되는 양분의 양은 A[r][c]이고, 입력으로 주어진다.
차근차근 순서에 맞게 하라는 대로 해보자!
#. Code
처음에는 완탐으로 접근해서 실행 시간이 너무 오래 걸렸다.
개선한 점은,
* 나무가 있는 위치만 체크
* 정렬은 초기에 한 번만.
초기에만 정렬해주면 더이상 정렬해줄 필요가 없다.
Queue에서 빼고 1살 나이를 먹고 다시 넣어주는 과정에서 어차피 나이순으로 다시 Queue에 들어가게 된다.
Queue는 구조상 정렬이 불가하지만, list type으로 형 변환 -> 정렬 -> 다시 queue로 형 변환으로 정렬할 수 있다.
1540ms -> 948ms 로 최적화할 수 있었지만..
더 줄일 수 있는 방법을 찾아봐야겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.StringTokenizer; public class BOJ16235_v2 { static int N, M, K, food[][], add[][]; static int[] dx = { -1, -1, 0, 1, 1, 1, 0, -1 }, dy = { 0, 1, 1, 1, 0, -1, -1, -1 }; static Queue<Tree> trees; static class Tree implements Comparable<Tree>{ int x, y, 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 Integer.compare(this.age, o.age); } } 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()); // 몇년 후 food = 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만큼 food[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 a = Integer.parseInt(st.nextToken()); trees.add(new Tree(x, y, a)); } // 초반에만 정렬해주면 더이상 정렬해줄 필요가 없다. Collections.sort((List<Tree>) trees); System.out.println(process()); } private static int process() { // K년 후 while(K-- > 0) { springToSummer(); fall(); winter(); } return trees.size(); } private static void winter() { // 겨울에는 S2D2가 땅을 돌아다니면서 땅에 양분을 추가 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { food[i][j] += add[i][j]; } } } // 가을에는 나무가 번식한다. private static void fall() { // 부모 나무를 보관 ArrayList<Tree> parents = new ArrayList<>(); int size = trees.size(); while (size-- > 0) { Tree now = trees.poll(); // 번식하는 나무는 나이가 5의 배수이어야 하며, if(now.age % 5 == 0) { // 인접한 8개의 칸에 나이가 1인 나무가 생긴다. for (int d = 0; d < 8; d++) { int xx = now.x + dx[d]; int yy = now.y + dy[d]; // 범위를 벗어나면 if(xx < 0 || xx >= N || yy < 0 || yy >= N) continue; trees.add(new Tree(xx, yy, 1)); } } parents.add(now); } // 아기 나무들이 먼저 Queue에 들어간 후 부모 나무를 Queue에 추가해주자. for (Tree t : parents) { trees.add(t); } } // 봄에는 나무가 자신의 나이만큼 양분을 먹고, 나이가 1 증가 // 하나의 칸에 여러 개의 나무가 있다면, 나이가 어린 나무부터 양분을 먹는다 private static void springToSummer() { // 죽은 나무 정보 저장 ArrayList<Tree> die = new ArrayList<>(); int size = trees.size(); while (size -- > 0) { Tree now = trees.poll(); // 만약, 땅에 양분이 부족해 자신의 나이만큼 양분을 먹을 수 없는 나무는 양분을 먹지 못하고 즉시 죽는다. if(food[now.x][now.y] - now.age < 0) { // 각각의 죽은 나무마다 나이를 2로 나눈 값이 나무가 있던 칸에 양분으로 추가된다 die.add(new Tree(now.x, now.y, now.age / 2)); } else { food[now.x][now.y] -= now.age; trees.add(new Tree(now.x, now.y, now.age + 1)); } } // 여름에는 봄에 죽은 나무가 양분으로 변하게 된다 for (Tree t : die) { food[t.x][t.y] += t.age; } } } | cs |
'PS > Problem_Solving' 카테고리의 다른 글
[BOJ] 3709. 레이저빔은 어디로(DFS).java (0) | 2020.11.11 |
---|---|
[BOJ] 2812.크게 만들기(Stack).java (0) | 2020.11.07 |
[SWEA]1868. 파핑파핑 지뢰찾기(dfs, bfs).java (0) | 2020.11.06 |
[SWEA] 2115. 벌꿀채취(부분집합, 조합).java (0) | 2020.11.06 |
[BOJ] 14698.전생했더니 슬라임 연구자였던 건에 대하여 (Hard)(PriorityQueue.java (0) | 2020.11.05 |