알고리즘/백준
[백준] 17144 - 미세먼지 안녕! (Java/자바)
행복한 개복치
2022. 4. 22. 21:31
https://www.acmicpc.net/problem/17144
17144번: 미세먼지 안녕!
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사
www.acmicpc.net
단순 구현문제였다. 문제에서 시키는 그대로 코드로 구현하면 된다.
공기청정기를 돌리는 부분에서 배열 회전 시키려는데 시작점을 잘못 생각해서 덮어쓰기 전 값을 어디에 둬야하나 한참 고민하다가 예전 코드 찾아보고 깨달았다;;
한 지점을 정해두고 그 값부터 덮도록 생각하니까 금방 꼬인 부분이 해결됐다.
이 문제의 경우, 공기청정기로 들어가는 공기를 기준으로 덮어가면 마지막 값은 공기청정기가 정화했기 때문에 처음 값을 따로 저장해 줄 필요도 없었다.
package Implementation;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main_BOJ_17144_미세먼지안녕_이선민_404ms {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int row = Integer.parseInt(st.nextToken());
int col = Integer.parseInt(st.nextToken());
int time = Integer.parseInt(st.nextToken());
int cleaner = -1; // 공기청정기 위쪽의 행
int[][] room = new int[row][col];
for (int i = 0, index = 0; i < row; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < col; j++) {
room[i][j] = Integer.parseInt(st.nextToken());
// 배열을 위에서부터 읽어오므로 먼저나오는 -1의 행이 cleaner에 들어가야함
if (room[i][j] == -1 && cleaner == -1) {
cleaner = i;
}
}
}
int[] dr = { 0, 1, 0, -1 };
int[] dc = { 1, 0, -1, 0 };
int rEnd = row - 1;
int cEnd = col - 1;
int[][] room2 = new int[row][col]; // 미세먼지 확산 후 방의 상태
while (time-- > 0) {
// 미세먼지를 새로 계산하기 위해 초기화
for (int i = 0; i < row; i++) {
Arrays.fill(room2[i], 0);
}
// 미세먼지 확산
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (room[i][j] != 0) { // 미세먼지가 있는 칸
int tiny = room[i][j] / 5; // 확산되는 양
int cnt = 0; // 확산된 방향의 개수
for (int k = 0; k < dr.length; k++) { // 사방으로 확산
int nr = i + dr[k];
int nc = j + dc[k];
// 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다
if (nr < 0 || nr >= row || nc < 0 || nc >= col || room[nr][nc] == -1) {
continue;
}
room2[nr][nc] += tiny;
cnt++;
}
room2[i][j] += room[i][j] - tiny * cnt;
}
}
} // 미세먼지 확산 완료
// 공기청정기 작동
int top = cleaner;
int bottom = cleaner + 1;
// 위쪽 : 반시계방향
for (int i = top - 1; i > 0; i--) { // 아래로 당기기
room2[i][0] = room2[i - 1][0];
}
for (int i = 0; i < cEnd; i++) { // 왼쪽으로 당기기
room2[0][i] = room2[0][i + 1];
}
for (int i = 0; i < top; i++) { // 위로 당기기
room2[i][cEnd] = room2[i + 1][cEnd];
}
for (int i = cEnd; i > 1; i--) { // 오른쪽으로 당기기
room2[top][i] = room2[top][i - 1];
}
room2[top][1] = 0; // 공기청정기에서 부는 바람은 정화됨
// 아래쪽 : 시계방향
for (int i = bottom + 1; i < rEnd; i++) { // 위로 당기기
room2[i][0] = room2[i + 1][0];
}
for (int i = 0; i < col - 1; i++) { // 왼쪽으로 당기기
room2[rEnd][i] = room2[rEnd][i + 1];
}
for (int i = rEnd; i > bottom; i--) { // 아래로 당기기
room2[i][cEnd] = room2[i - 1][cEnd];
}
for (int i = col - 1; i > 1; i--) { // 오른쪽으로 당기기
room2[bottom][i] = room2[bottom][i - 1];
}
room2[bottom][1] = 0; // 공기청정기에서 부는 바람은 정화됨
// 공기청정기까지 돌린 이후의 방 상태(room2)를 원본배열(room)에 깊은 복사
for (int i = 0; i < room2.length; i++) {
System.arraycopy(room2[i], 0, room[i], 0, room2[0].length);
}
} // end of while
int ans = 0; // 남아있는 미세먼지의 양
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (room[i][j] > 0) {
ans += room[i][j];
}
}
}
System.out.println(ans);
} // end of main
} // end of class