티스토리 뷰
문제 - (주소)
전형적인 시뮬레이션 문제였다.
구현하라는대로 구현하면 됐다. 단 구현시 알아두면 좋은 것들이 있는데 그것을 소개하겠다.
1. 방향 조회하기
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
위, 오른, 아래, 위 방향으로 이동하기 위해 초기화한 배열이다.
어떻게 사용하냐면
map이라는 이차원 배열이 있다고 할 때,
for (int d = 0; d <= 3; d++) {
int moveX = i + dx[d];
int moveY = j + dy[d];
map[moveX][moveY];
}
이렇게 하면 d가 0~3까지 4번동안 dx, dy를 통해 map을 위, 오른, 아래, 위 방향으로 조회가 가능하다.
2. 조회하는 방향 응용하기
문제에서 공기청정기 바람의 이동방향이 있었는데, 나는 앞서 언급한 방향 조회하기를 응용해봤다.
위쪽의 공기청정기 바람은 오른 -> 위 -> 왼 -> 아래 방향으로 흐르고
아래쪽의 공기청정기 바람은 오른 -> 아래 -> 왼 -> 위 방향으로 흐른다.
위,오른,아래,왼이 차례로 dx, dy의 0,1,2,3 인덱스임을 이용해서 배열을 선언해서 순회하도록 구현했다.
static int[] upSideDir = {1, 0, 3, 2};
static int[] downSideDir = {1, 2, 3, 0};
for (int i = 0; i <= 3; i++) {
upSideAirPosX += dx[upSideDir[i]];
upSideAirPosY += dy[upSideDir[i]];
downSideAirPosX += dx[downSideDir[i]];
downSideAirPosY += dy[downSideDir[i]];
}
📌주의할 점
- 헷갈릴 수 있으므로 손으로 그려보면서 풀어보는 것을 추천한다
- temp 배열을 사용한다면, 반복문마다 제대로 map을 업데이트 해줬는지 반드시 확인한다.
😅실수
- 위쪽 공기청정기와 아래쪽 공기청정기의 바람 이동방향 로직을 구현하는 것이 비슷해서 복.붙을 했다면 수정되야 할 부분들이 정확히 수정되었는지 섬세하게 확인할 필요가 있다... 여기서 실수하면 원인 찾기가 더 힘들어진다 ㅠㅠ 디버깅을 돌린다는 것 자체가 시간에 부담됨
- 문제를 잘 보고 문제 그대로 구현할 때, 기존에 있던 값에 더해주는 것인지 초기화하는 것인지 주의깊게 보고 코딩하자
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/**
* 1시간 30분
*/
public class Dust {
static int r;
static int c;
static int t;
static int[][] map;
static int[] airCleanerUpSide;
static int[] airCleanerDownSide;
static int answer = 0;
static int[] dx = {-1, 0, 1, 0}; // 위, 오른, 아래, 위 방향
static int[] dy = {0, 1, 0, -1}; // 위, 오른, 아래, 위 방향
static int[] upSideDir = {1, 0, 3, 2};
static int[] downSideDir = {1, 2, 3, 0};
static void simulate() {
int time = 0;
while (time != t) {
int[][] temp = new int[r][c]; // 이 시간대에 퍼질 미세먼지 구하기
// 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (map[i][j] == 0) continue;
// 현재 i,j에서 4방향 확산기키기
int currentPosDust = map[i][j];
int effectDust = currentPosDust / 5;
// 확산될 방향 찾아서 값 넣고 갯수 세기
int effectArea = 0; // 확산된 방향 수
for (int d = 0; d <= 3; d++) {
int moveX = i + dx[d];
int moveY = j + dy[d];
if (!(moveX < 0 || moveY < 0 || moveX >= r || moveY >= c || map[moveX][moveY] == -1)) {
temp[moveX][moveY] += effectDust;
effectArea++;
}
}
// 남은 미세먼지양 적용
temp[i][j] += /*실수*/ currentPosDust - ((currentPosDust / 5) * effectArea);
}
}
// 확산된 결과 temp로 map 업데이트
temp[airCleanerUpSide[0]][airCleanerUpSide[1]] = -1;
temp[airCleanerDownSide[0]][airCleanerDownSide[1]] = -1;
map = temp;
// 공기청정기가 작동한다.
int upSideAirPosX = airCleanerUpSide[0];
int upSideAirPosY = airCleanerUpSide[1];
int downSideAirPosX = airCleanerDownSide[0];
int downSideAirPosY = airCleanerDownSide[1];
int[][] airTemp = new int[r][c];
int preUpDust = 0;
int preDownDust = 0;
for (int i = 0; i <= 3; i++) { // 공기청정기 4가지 방향으로 이동함
// 위쪽 공기청정기 i번째 방향으로 계속 이동
while (true) {
upSideAirPosX += dx[upSideDir[i]];
upSideAirPosY += dy[upSideDir[i]];
if (upSideAirPosX < 0 || upSideAirPosY < 0 || upSideAirPosX >= r || upSideAirPosY >= c || map[upSideAirPosX][upSideAirPosY] == -1) {
upSideAirPosX -= dx[upSideDir[i]]; // 이전위치로 돌아가기
upSideAirPosY -= dy[upSideDir[i]];
break;
}
airTemp[upSideAirPosX][upSideAirPosY] = preUpDust;
preUpDust = map[upSideAirPosX][upSideAirPosY];
}
// 아래쪽 공기청정기 i번째 방향으로 계속 이동
/* 위에서 이미 구현한 것과 비슷하다고 밑에 복붙할거면
* 바꿔야할 값들 신중하게 보고 바꾸자... 여기서 실수로 시간 많이 뺏어먹음 */
while (true) {
downSideAirPosX += dx[downSideDir[i]];
downSideAirPosY += dy[downSideDir[i]];
if (downSideAirPosX < 0 || downSideAirPosY < 0 || downSideAirPosX >= r || downSideAirPosY >= c || map[downSideAirPosX][downSideAirPosY] == -1) {
downSideAirPosX -= dx[downSideDir[i]]; // 이전위치로 돌아가기
downSideAirPosY -= dy[downSideDir[i]];
break;
}
airTemp[downSideAirPosX][downSideAirPosY] = preDownDust;
preDownDust = map[downSideAirPosX][downSideAirPosY];
}
}
// 바람으로 바뀐 모양으로 map 업데이트
for (int i = 0; i < r; i++) {
if (i == 0 || i == r - 1 || i == airCleanerUpSide[0] || i == airCleanerDownSide[0]) continue;
for (int j = 0; j < c; j++) {
if (j == 0 || j == c - 1 ) continue;
airTemp[i][j] = map[i][j];
}
}
airTemp[airCleanerUpSide[0]][airCleanerUpSide[1]] = -1;
airTemp[airCleanerDownSide[0]][airCleanerDownSide[1]] = -1;
map = airTemp;
time++;
}
for (int[] m : map) {
for (int _m : m) {
if (_m == -1) continue;
answer += _m;
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
t = Integer.parseInt(st.nextToken());
map = new int[r][c];
for (int i = 0; i < r; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < c; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if (map[i][j] == -1)
if (airCleanerUpSide == null) airCleanerUpSide = new int[]{i, j};
else airCleanerDownSide = new int[]{i, j};
}
}
simulate();
System.out.println(answer);
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 16234번 / Java / 인구 이동 (0) | 2020.06.07 |
---|---|
[백준] 16236번 / Java / 아기상어 - BFS 풀이 (0) | 2020.06.07 |
[백준] 15683번 / Java / 감시 - 완전탐색 (0) | 2020.05.21 |
[백준] 14889번 / Java / 스타트와 링크 - 재귀풀이 (0) | 2020.05.20 |
[백준] 14501번 / Java / 퇴사 - 재귀풀이 (0) | 2020.05.19 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 아기상어
- 백준
- 프로그래머스
- 사다리 조작
- 재귀
- 완전탐색
- 14891
- java
- header
- BOJ
- 코딩테스트
- Greedy
- 구명보트
- 자바
- 구현
- 톱니바퀴
- dfs
- 그리디
- 코테
- withCredentials
- 큰 수 만들기
- 코딩테스트 연습
- 인구이동
- 브라우저 요청
- 시뮬레이션
- 드래곤 커브
- 우선순위큐
- 16234
- Access-Control-Allow-Origin
- 배열순회
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함