티스토리 뷰
생각
Github - https://github.com/hellojdh/Code/blob/master/src/baekjoon/q10000/Q16235.java 상도가 나무 재테크를 한다. 봄 여름 가을 겨울에 각 각 일어나는 일이 다르다. 봄에는 나무가 땅의 양분을 자기 나이만큼 흡수한다. 같은 땅에서는 나이가 어린 나무부터 양분을 흡수한다. 이 때 자기 나이보다 땅에 양분이 없으면 그 나무는 즉사한다. 여름에는 봄에 즉사했던 나무들이 해당 나무의 나이/2 만큼 해당 좌표의 땅에 양분이 된다. 가을에는 나무의 나이가 5의 배수이면 주변 모든 좌표(8개)에 나이가 1인 나무를 퍼트린다. 겨울에는 로봇 S2D2가 땅을 돌아다니면서 입력으로 주어진 해당 땅의 양분을 공급한다. 위 같은 과정을 거치면 1년이 흐른다. K년이 흘렀을 때, 살아남은 나무의 개수를 출력하여라.
처음 생각
한 좌표에 여러개의 나무가 있을 수 있으므로, 이를 고려하기 위해서 다양한 방법을 사용할 수 있을 것이다. 배열로 만들어 볼까하다가 List가 문뜩 떠올라서 List로 구현하였다.
▶ List로 (x,y) 좌표에 대한 여러 나무의 정보가 들어있어야하므로, 3중 List를 아래와 같이 구현하였다.
▶ List안에 ArrayList(x좌표)가 있고 그 안에 ArrayList(y좌표)가 있으며 해당 칸에 들어가야하는 나무들의 정보를 가지고 있는 Pair 객체로 타입을 구현해주었다.
1 | static List<ArrayList<ArrayList<Pair>>> list = new ArrayList<>(); |
▶ 위와 같이 구현해주었을 경우는 List를 미리 다 채워놓아야 한다. 아래의 방법으로 x와 y에 대한 ArrayList를 add 시켜 주었다. x에 대응하는 n개를 add 시켜준 뒤, 각 x에 대한 y 대응으로 n개를 add시켜 주었다.
1 2 3 4 5 6 | // n개의 arrayList 생성 for(int i=0;i<n;i++) { list.add(new ArrayList<>()); for(int j=0;j<n;j++) list.get(i).add(new ArrayList<>()); } |
다음 생각
좌표 (x,y)에 대한 나무들을 넣을 방법을 구현하였으므로, 봄부터 여름 가을 겨울 순으로 차례대로 구현을 하였다.
▶ 삼중 반복문을 돌면서 아래와 같이 List에서 x,y 값에 따른 나무들을 검사해 주었다.
1 | list.get(i).get(j).get(k) |
▶ 봄에는 해당 좌표의 양분을 가지고 해당 나무가 살아남을 수 있나를 검사한다. 나이가 어린 나무 부터 검사를 하기 때문에 한 번 나무가 죽으면 그 뒤의 나무도 모두 죽기 때문에 여름과 합쳐서 작성해도 무방할 것 같다. 작성은 나무가 죽을 경우 나무 상태인 v 값을 1에서 0으로 바꿔주었다.
▶ 여름에는 다시 반복문을 돌면서 나무들을 검사해 죽은 상태(0)일 경우 해당 나무의 나이/2 만 큼 해당 좌표에 양분으로 추가해주었다. 양분이 되면 해당 나무는 사라져야 하기 때문에 remove(k)를 통해 없애준 후, list의 index가 한 칸씩 땡겨져 왔을 것이므로 k--를 통해 해당 index를 재 검사하도록 하였다.
▶ 가을에는 다시 반복문을 돌면서 나무들의 나이를 검사해 %5가 0이라면 즉, 나이가 5의 배수라면 주변 모든좌표(8 방향)의 List에 나무를 추가해 주었다. 이 때, 나무의 나이는 1이므로 add(0,나무)로 0번 index에 추가시켜 주었다. 봄에 어린 나무 부터 검사를 해야하기 때문이다.
▶ 겨울에는 미리 입력 받아놓았던, 양분 배열을 사용하고 있는 배열에 더해주었다.
다다음 생각
문제를 잘 읽어야한다.
▶ 좌표의 입력으로 들어오는 수가 0부터 시작이 아닌 1부터 시작이기 때문에 -1 처리를 해주었다.
▶ 입력으로 들어오는 양분 표는 겨울에 로봇 S2D2가 뿌리는 양분이지 처음 모든 땅의 양분은 5이다.
다다다음 생각
뒷 번호의 테스트 케이스가 틀리게 나와서 보니 가을에 8방향으로 나무들을 퍼트릴 때, 반복문 안에서 좌표 변환을 위해 사용하고 있는 변수인 z가 아닌 i를 적어놓아서 조금만 뿌려져서 잘 못 된 값이 나왔었다.
▶ 반복문 사용할 때 잘 적어야 겠다.
방안
1) 항상 변수 이름 확인 잘하기.
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 | package baekjoon.q10000; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Q16235 { static int n,m,k; static int[][] arr,copy; static List<ArrayList<ArrayList<Pair>>> list = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); // n*n 배열 m = sc.nextInt(); // 나무 정보 수 k = sc.nextInt(); // K년이 지난후. arr = new int[n][n]; copy = new int[n][n]; // 추가 되어야할 양분 // n개의 arrayList 생성 for(int i=0;i<n;i++) { list.add(new ArrayList<>()); for(int j=0;j<n;j++) list.get(i).add(new ArrayList<>()); } // 초기 양분값 for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { copy[i][j] = sc.nextInt(); arr[i][j] = 5; // 초기 양분은 5 } } // m개의 줄에 상도가 심은 나무정보수 (x,y), 나무나이 for(int i=0;i<m;i++) { int x = sc.nextInt(); int y = sc.nextInt(); int age = sc.nextInt(); list.get(x-1).get(y-1).add(new Pair(x-1, y-1, 1, age)); } // K년 동안 for(int i=0;i<k;i++) { // 1년은 4계절 solveSpring(); solveSummer(); solveFall(); solveWinter(); } // k년이 흐른 후 살아있는 나무 조사 int result = 0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { result += list.get(i).get(j).size(); } } System.out.println(result); } // 겨울에는 땅에 양분을 추가한다. 각 칸에 추가되는 양분은 초기 입력 양분이다. private static void solveWinter() { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { arr[i][j] += copy[i][j]; } } } // 가을에는 나무가 번식한다. 나이가 5의 배수인 나무의 // 인접 8칸에 나이가 1인 나무가 생긴다. static int[][] dir = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}}; private static void solveFall() { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { for(int k=0;k<list.get(i).get(j).size();k++) { // age가 5의 배수가 아니라면 패스 if(list.get(i).get(j).get(k).age%5!=0) continue; for(int z=0;z<8;z++) { int tx = i+dir[z][0]; int ty = j+dir[z][1]; if(tx<0 || ty<0 || tx>=n || ty>=n) continue; // 해당 칸이 나이가 1인 나무 생성 list.get(tx).get(ty).add(0,new Pair(tx, ty, 1, 1)); } } } } } // 여름에는 봄에 죽은 나무가 양분으로 변한다. // 죽은 나무의 나이/2가 양분으로 해당칸에 추가된다. private static void solveSummer() { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { // 해당 좌표의 나무들을 보면서 0인것을 없애주자. for(int k=0;k<list.get(i).get(j).size();k++) { // 죽은 나무라면 if(list.get(i).get(j).get(k).v==0) { arr[i][j] += list.get(i).get(j).get(k).age/2; // k--를 해주어 없어진 걸로 인한 영향을 없앤다. list.get(i).get(j).remove(k); k--; } } } } } // 봄에는 나무가 나이만 큼 양분을 먹고 나이가 +1 (자신칸만 가능) // 하나의 칸에 여러 개의 나무가 있따면 나이 어린 나무가 먼저 먹는다. // 양분이 부족해 먹지못하면 먹지 않고 바로 즉사 private static void solveSpring() { for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { // 나무 검사 for(int k=0;k<list.get(i).get(j).size();k++) { if(list.get(i).get(j).get(k).age>arr[i][j]) { // 나무의 나이가 더 크다면 즉사 list.get(i).get(j).get(k).v = 0; }else { // 해당지역 나이 만큼 양분 감소 arr[i][j] -= list.get(i).get(j).get(k).age++; } } } } } static class Pair{ int x,y; // 위치 int v; // 상태 (1살음,0죽음) int age; // 나이 Pair(int x,int y,int v,int age){ this.x = x; this.y = y; this.v = v; this.age = age; } } } |
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 13908번 비밀번호 (0) | 2018.10.29 |
---|---|
[백준] 16236번 아기 상어 (0) | 2018.10.27 |
[백준] 16234번 인구 이동 (0) | 2018.10.25 |
[백준] 14395번 4연산 (9) | 2018.10.25 |
[백준] 3184번 양 (0) | 2018.10.25 |
- Total
- Today
- Yesterday