16235번: 나무 재테크
부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터
www.acmicpc.net
문제 읽기
실수 없이 구현하면 되는 시뮬레이션 문제이다. 문제를 읽으면서 실수할 수 있는 부분을 체크하면서 읽었다.
- r, c는 1부터 시작
- 초기 양분은 5부터
그 다음 자료구조를 정했다.
- 나무 : 나이만 필요하므로 그냥 int형
- Cell : 양분의 양(int), 살아있는 나무(list), 죽은 나무(list)
나무는 그냥 int형으로 정했고 각각의 cell은 class로 정의했다.
코드
package ps.ㄱSolving;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
public class BOJ_G3_16235_나무재테크 {
static class Cell{
int good;
List<Integer> liveTree;
List<Integer> deadTree;
public Cell(int good, List<Integer> liveTree, List<Integer> deadTree) {
super();
this.good = good;
this.liveTree = liveTree;
this.deadTree = deadTree;
}
}
static int N, M, K; //NxN, 나무 수, K년
static Cell[][] map;
static int[][] A;
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(in.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
//A입력
A = new int[N][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(in.readLine());
for (int j = 0; j < N; j++) {
A[i][j] = Integer.parseInt(st.nextToken());
}
}
//맵 초기화
map = new Cell[N][N];
//r, c 다 해줘야 함. 아니면 null pointer error
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
//초기에는 5 만큼의 양분 존재
map[r][c] = new Cell(5, new ArrayList<>(), new ArrayList<>());
}
}
//나무 입력
for (int i = 0; i < M; i++) {
st = new StringTokenizer(in.readLine());
int r = Integer.parseInt(st.nextToken()) - 1;
int c = Integer.parseInt(st.nextToken()) - 1;
int age = Integer.parseInt(st.nextToken());
map[r][c].liveTree.add(age);
}
//logic
while(K-- > 0) {
//봄 : 양분 섭취
spring();
//여름 : 죽은 나무가 양분으로
summer();
//가을 : 나무 번식. age = 5의 배수
fall();
//겨울 : 기기가 양분 추가
winter();
}
//K년 후.. 살아있는 나무의 개수
int cnt = 0;
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
cnt += map[r][c].liveTree.size();
}
}
System.out.println(cnt);
}
private static void spring() {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
//매 cell마다 나무들을 스캔하여 나이 먹임
//오름차순 정렬 후 스캔
Collections.sort(map[r][c].liveTree); //디폴트가 오름차순
int deadIdx = -1;
for (int i = 0; i < map[r][c].liveTree.size(); i++) {
//나이만큼의 양분이 있는지 체크
int age = map[r][c].liveTree.get(i);
if (map[r][c].good >= age) {
map[r][c].good -= age;
map[r][c].liveTree.set(i, age+1); //나이 증가!!
}
else {
//죽음. 오름차순 정렬이기 때문에 뒤에 있는 것도 다 죽음. 반복문 밖에서 처리
deadIdx = i; //i~끝까지 다 죽음
break; //빼먹음!!
}
}
//죽은 나무는 live에서 뺴고, dead에 넣음. remove를 쓰기 위해 끝에서부터 지움
if (deadIdx != -1) {
for (int i = map[r][c].liveTree.size() - 1; i >= deadIdx; i--) {
int deadTree = map[r][c].liveTree.get(i);
map[r][c].liveTree.remove(i);
map[r][c].deadTree.add(deadTree);
}
}
}
}
}
private static void summer() {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
for (int age : map[r][c].deadTree) {
//나이 / 2 = 새로운 양분
map[r][c].good += (age / 2); //소수점 아래는 자동 버림
}
map[r][c].deadTree.clear(); //다 양분으로 변함
}
}
}
static int[] dr = {-1, -1, -1, 0, 0, 1, 1, 1};
static int[] dc = {-1, 0, 1, -1, 1, -1, 0, 1};
private static void fall() {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
for (int age : map[r][c].liveTree) {
if (age % 5 == 0) {
//인접 8방에 나이 1인 나무 생성
spread(r, c);
}
}
}
}
}
private static void spread(int r, int c) {
for (int di = 0; di < 8; di++) {
int nr = r + dr[di];
int nc = c + dc[di];
if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;
//아기나무
map[nr][nc].liveTree.add(1);
}
}
private static void winter() {
for (int r = 0; r < N; r++) {
for (int c = 0; c < N; c++) {
map[r][c].good += A[r][c];
}
}
}
}
실수한 부분
원소 삭제 : 하려고 한 게 있으면 까먹지 않게 주석으로 메모하자
죽은 나무를 살아있는 나무 리스트에서 지울 때 deadIdx를 정해서 지웠는데, break가 빠져서 마지막 답이 나오지 않았다. 이 부분 주의 !
이차원 배열 할당 : NULL Pointer Error
사용자 정의 class로 이차원 배열 선언 시 이중 for문을 통해 일일이 초기화 필수!!
'Algorithm > Simulation' 카테고리의 다른 글
BOJ G1 2933 미네랄 JAVA (0) | 2024.01.17 |
---|---|
BOJ G2 19236 청소년 상어 JAVA (0) | 2023.07.15 |
BOJ G5 20055 컨베이어 벨트 위의 로봇 JAVA (0) | 2023.07.15 |
BOJ G5 21610 마법사 상어와 비바라기 JAVA (0) | 2023.07.15 |
BOJ G4 15685 드래곤커브 JAVA (0) | 2023.07.02 |