반응형
https://www.acmicpc.net/problem/17144
17144번: 미세먼지 안녕!
미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사
www.acmicpc.net
풀이
문제에 이해하기 쉽게 설명이 잘 적혀있으니까 생략하겠다.
위 문제에서는 두 개의 일이 순서대로 이루어진다.
- 미세먼지 확산: 4방향으로 먼지가 확산된다.
- 공기청정기 작동: 위 칸과 아래 칸의 바람이 방향이 서로 다르며 한 칸씩 먼지를 밀어낸다.
미세먼지 확산은 dfs 혹은 bfs를 이해하고 있고 관련된 문제를 풀어봤다면 쉽게 해결할 수 있을 것이다.
public static void DustSpread() {
while (!q.isEmpty()) {
Position now = q.poll();
if (now.v < 5) continue;
int cnt = 0;
int DustSpreadV = now.v / 5;
for (int i=0; i<4; i++) {
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if (nx < 0 || ny < 0 || nx > R-1 || ny > C-1 || map[nx][ny] == -1) continue;
map[nx][ny] += DustSpreadV;
cnt++;
}
map[now.x][now.y] -= DustSpreadV * cnt;
}
}
4방향으로 한 번씩만 확산이 되기 때문에 visited 처리를 한다거나 queue에 넣을 필요는 없다. 범위를 벗어나는 부분만 신경써주면 된다.
공기청정기는 위 칸과 아래 칸의 바람 방향이 다르기 때문에 구분해서 실행해주면 된다.
public static void AirCleaner() {
// [위] 아래
for (int i=top-1; i>0; i--) {
map[i][0] = map[i-1][0];
}
// [위] 왼쪽
for (int i=0; i<C-1; i++) {
map[0][i] = map[0][i+1];
}
// [위] 위
for (int i=0; i<top; i++) {
map[i][C-1] = map[i+1][C-1];
}
// [위] 오른쪽
for (int i=C-1; i>1; i--) {
map[top][i] = map[top][i-1];
}
// [아래] 위로
for (int i=bot+1; i<R-1; i++) {
map[i][0] = map[i+1][0];
}
// [아래] 왼쪽으로
for (int i=0; i<C-1; i++) {
map[R-1][i] = map[R-1][i+1];
}
// [아래] 아래로
for (int i=R-1; i>bot; i--) {
map[i][C-1] = map[i-1][C-1];
}
// [아래] 오른쪽으로
for (int i=C-1; i>1; i--) {
map[bot][i] = map[bot][i-1];
}
map[top][1] = 0;
map[bot][1] = 0;
}
바람의 방향대로 미세먼지를 한 칸씩 밀어낸 후에 공기청정기 바람의 시작점을 0으로 초기화해주어야한다.
두 개의 과정을 입력된 시간만큼 반복해서 돌려주면 된다. 한 번의 과정을 거쳤다면 다시 미세먼지의 위치를 queue에 입력해주고 반복한다. 문제가 길고 조건이 많은 것처럼 보이지만 별로 어렵지 않은 문제이다.
<최종코드>
import java.io.*;
import java.util.*;
public class Main {
static int[] dx = {1, 0, -1, 0};
static int[] dy = {0, 1, 0, -1};
static int R, C, T, airM, top, bot;
static int[][] map;
static Queue<Position> q;
public static class Position {
int x;
int y;
int v;
public Position (int x, int y, int v) {
this.x = x;
this.y = y;
this.v = v;
}
}
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][0] == -1) {
airM = i;
}
}
}
int time = 0;
top = airM-1;
bot = airM;
while (time < T) {
CheckDust(); // 미세먼지 위치 확인
DustSpread(); // 미세먼지 확산
AirCleaner(); // 공기청정기
time++;
}
int ans = 0;
for (int i=0; i<R; i++) {
for (int j=0; j<C; j++) {
if (map[i][j] > 0) {
ans += map[i][j];
}
}
}
System.out.println(ans);
}
public static void CheckDust() {
q = new LinkedList<>();
for (int i=0; i<R; i++) {
for (int j=0; j<C; j++) {
if (map[i][j] > 0) {
q.add(new Position(i, j, map[i][j]));
}
}
}
}
public static void DustSpread() {
while (!q.isEmpty()) {
Position now = q.poll();
if (now.v < 5) continue;
int cnt = 0;
int DustSpreadV = now.v / 5;
for (int i=0; i<4; i++) {
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if (nx < 0 || ny < 0 || nx > R-1 || ny > C-1 || map[nx][ny] == -1) continue;
map[nx][ny] += DustSpreadV;
cnt++;
}
map[now.x][now.y] -= DustSpreadV * cnt;
}
}
public static void AirCleaner() {
// [위] 아래
for (int i=top-1; i>0; i--) {
map[i][0] = map[i-1][0];
}
// [위] 왼쪽
for (int i=0; i<C-1; i++) {
map[0][i] = map[0][i+1];
}
// [위] 위
for (int i=0; i<top; i++) {
map[i][C-1] = map[i+1][C-1];
}
// [위] 오른쪽
for (int i=C-1; i>1; i--) {
map[top][i] = map[top][i-1];
}
// [아래] 위로
for (int i=bot+1; i<R-1; i++) {
map[i][0] = map[i+1][0];
}
// [아래] 왼쪽으로
for (int i=0; i<C-1; i++) {
map[R-1][i] = map[R-1][i+1];
}
// [아래] 아래로
for (int i=R-1; i>bot; i--) {
map[i][C-1] = map[i-1][C-1];
}
// [아래] 오른쪽으로
for (int i=C-1; i>1; i--) {
map[bot][i] = map[bot][i-1];
}
map[top][1] = 0;
map[bot][1] = 0;
}
}
내가 생각한 시간 복잡도: O(RCT)
반응형
'알고리즘 > 구현 & 그리디 & 브루트포스' 카테고리의 다른 글
[백준]JAVA - 13460번: 구슬 탈출 2 (0) | 2022.12.12 |
---|---|
[백준]JAVA - 14890번: 경사로 (0) | 2022.12.04 |
[백준]JAVA - 15683번: 감시 (0) | 2022.11.22 |
[백준]JAVA - 10773번: 제로 (0) | 2022.11.21 |
[백준]JAVA - 1913번: 달팽이 (0) | 2022.11.20 |