본문 바로가기

Algorithm/BOJ

[ BOJ ] 17144. 미세먼지 안녕! G5 JAVA

반응형

 

 



 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사

www.acmicpc.net

문제 이해
공기청정기는 항상 1번 열에 설치되어 있고, 크기는 두 행을 차지한다. 공기청정기가 설치되어 있지 않은 칸에는 미세먼지가 있고, (r, c)에 있는 미세먼지의 양은 Ar,c이다.
 1초 동안 아래 적힌 일이 순서대로 일어난다.
  1. 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다.
    • (r, c)에 있는 미세먼지는 인접한 네 방향으로 확산된다.
    • 인접한 방향에 공기청정기가 있거나, 칸이 없으면 그 방향으로는 확산이 일어나지 않는다.
    • 확산되는 양은 Ar,c/5이고 소수점은 버린다.
    • (r, c)에 남은 미세먼지의 양은 Ar,c - (Ar,c/5)×(확산된 방향의 개수) 이다.
  2. 공기청정기가 작동한다.
    • 공기청정기에서는 바람이 나온다.
    • 위쪽 공기청정기의 바람은 반시계방향으로 순환하고, 아래쪽 공기청정기의 바람은 시계방향으로 순환한다.
    • 바람이 불면 미세먼지가 바람의 방향대로 모두 한 칸씩 이동한다.
    • 공기청정기에서 부는 바람은 미세먼지가 없는 바람이고, 공기청정기로 들어간 미세먼지는 모두 정화된다.
아이디어
- 시뮬레이션 문제.
- 그냥 하라는데로 따라서 쭈욱 코드를 짰다.
- 클래스를 하나 따로 빼서 먼지의 좌표값, 먼지크기를 넣어줬다.

먼지를 넣을 클래스
static class Pos {
        int x, y, w;

        public Pos(int x, int y, int w) {
        this.x = x;
        this.y = y;
        this.w = w;
        }
}
입력 구간

입력받을 때 미리 공청기 위치랑 먼지 위치를 받아놨다.

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];
dusts = new ArrayList<>();
ac = new ArrayList<>();
check = 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] == airCleaner) {
            	ac.add(new Pos(i, j,map[i][j])); // 공청기 위치를 담는다.
            }
            else if (map[i][j] > 0) {
            	dusts.add(new Pos(i, j,map[i][j]));// 미세먼지위치를 담는다.
            }
	  }
}
먼지 찾아서 출력하기
int ans = 0;
// T초 동안 시행한다.
for (int i = 0; i < T; ++i) {
      // 1. 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다
      moveDust();
      // 2. 공청기가 작동한다.
      actAirCleaner();
      // 3. dusts 리스트를 갱신한다.
      ans = updateDustsPosandSum();
}
System.out.println(ans);
미세먼지 확산시키기
private static void moveDust() {
      for (Pos dust : dusts) {
            int cnt = 0;// 확산된 개수
            int val = dust.w;//미세먼지크기
            int spread = val/5;//확산 미세먼지 크기
            for (int d = 0; d < 4; ++d) {
                  int nx = dust.x + dx[d];
                  int ny = dust.y + dy[d];
                  if(isInArea(nx, ny) && map[nx][ny] != airCleaner) { // 영역안이고, 공청기아니면
                        map[nx][ny] += spread; // 확산해주고
                        cnt++; // 카운트
                  }
            }
            map[dust.x][dust.y] -= (val/5) * cnt; // 새로운 값으로 갱신
      }
}
공청기 작동시키기 (윗부분은 반시계, 아랫부분은 시계)  
private static void actAirCleaner() {
      // upper ac[0]
      Pos upper = ac.get(0);
      // 0,0 -> upper.x - 1, upper.y 까지 내린다.
      for(int i= upper.x-1; i > 0 ; --i) map[i][0] = map[i-1][0];
      // 0,C-1 -> 0,0 까지
      for(int j=0; j<C-1; ++j) map[0][j]=map[0][j+1];
      // upper.x , C-1 -> 0,C-1까지
      for(int i=0;i<upper.x;++i) map[i][C-1] = map[i+1][C-1];
      // upper.x, upper.y -> upper.x, C-1 까지 
      for(int j=C-1;j > upper.y+1;--j) map[upper.x][j] = map[upper.x][j-1];
      map[upper.x][upper.y+1] = 0;

      // lower ac[1]
      Pos lower = ac.get(1);
      // lower.x+1,0 -> R-1,0
      for(int i=lower.x+1;i<R-1;++i) map[i][0]=map[i+1][0];
      // R-1,0 -> R-1,C-1 o
      for(int j=0; j<C-1;++j) map[R-1][j] = map[R-1][j+1];
      // R-1,C-1 -> lower.x +1, C-1 o
      for(int i=R-1; i>lower.x;--i) map[i][C-1] =map[i-1][C-1];
      // lower.x, C-1 -> lower.x, lower.y_1
      for(int j=C-1; j>lower.y+1; --j) map[lower.x][j]=map[lower.x][j-1];
      map[lower.x][lower.y+1] = 0;
}
미세먼지 총합이랑 미세먼지 위치 등록하기
private static int updateDustsPosandSum() {
      dusts = new ArrayList<>();
      int sum = 0;
            for(int i=0;i<R;++i) {
                  for(int j=0;j<C;++j) {
                        if(map[i][j] > 0) {
                              dusts.add(new Pos(i,j,map[i][j]));
                              sum += map[i][j];
                              check[i][j] = 1;
                        }
                  }
            }
      return sum;
}

코드
import java.io.*;
import java.util.*;

public class Main {
	static class Pos {
		int x, y, w;

		public Pos(int x, int y, int w) {
			this.x = x;
			this.y = y;
			this.w = w;
		}
	}

	static int R, C, T, map[][];
	static final int airCleaner = -1;
	static int[] dx = { -1, 1, 0, 0 };
	static int[] dy = { 0, 0, -1, 1 };
	static ArrayList<Pos> ac;
	static ArrayList<Pos> dusts;
	static int[][] check;
	public static void main(String[] args) throws Exception {
		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];
		dusts = new ArrayList<>();
		ac = new ArrayList<>();
		check = 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] == airCleaner) {
					ac.add(new Pos(i, j,map[i][j])); // 공청기 위치를 담는다.
				}
				else if (map[i][j] > 0) {
					dusts.add(new Pos(i, j,map[i][j]));// 미세먼지위치를 담는다.
				}
			}
		}
		int ans = 0;
		// T초 동안 시행한다.
		for (int i = 0; i < T; ++i) {
			// 1. 미세먼지가 확산된다. 확산은 미세먼지가 있는 모든 칸에서 동시에 일어난다
			moveDust();
			// 2. 공청기가 작동한다.
			actAirCleaner();
			// 3. dusts 리스트를 갱신한다.
			ans = updateDustsPosandSum();
		}
		System.out.println(ans);
	}
	
	private static int updateDustsPosandSum() {
		dusts = new ArrayList<>();
		int sum = 0;
		for(int i=0;i<R;++i) {
			for(int j=0;j<C;++j) {
				if(map[i][j] > 0) {
					dusts.add(new Pos(i,j,map[i][j]));
					sum += map[i][j];
					check[i][j] = 1;
				}
			}
		}
		return sum;
	}

	private static void actAirCleaner() {
		// upper ac[0]
		Pos upper = ac.get(0);
		// 0,0 -> upper.x - 1, upper.y 까지 내린다.
		for(int i= upper.x-1; i > 0 ; --i) map[i][0] = map[i-1][0];
		// 0,C-1 -> 0,0 까지
		for(int j=0; j<C-1; ++j) map[0][j]=map[0][j+1];
		// upper.x , C-1 -> 0,C-1까지
		for(int i=0;i<upper.x;++i) map[i][C-1] = map[i+1][C-1];
		// upper.x, upper.y -> upper.x, C-1 까지 
		for(int j=C-1;j > upper.y+1;--j) map[upper.x][j] = map[upper.x][j-1];
		map[upper.x][upper.y+1] = 0;

		// lower ac[1]
		Pos lower = ac.get(1);
		// lower.x+1,0 -> R-1,0
		for(int i=lower.x+1;i<R-1;++i) map[i][0]=map[i+1][0];
		// R-1,0 -> R-1,C-1 o
		for(int j=0; j<C-1;++j) map[R-1][j] = map[R-1][j+1];
		// R-1,C-1 -> lower.x +1, C-1 o
		for(int i=R-1; i>lower.x;--i) map[i][C-1] =map[i-1][C-1];
		// lower.x, C-1 -> lower.x, lower.y_1
		for(int j=C-1; j>lower.y+1; --j) map[lower.x][j]=map[lower.x][j-1];
		map[lower.x][lower.y+1] = 0;
	}

	private static void moveDust() {
		for (Pos dust : dusts) {
			int cnt = 0;
			int val = dust.w;
			int spread = val/5;
			for (int d = 0; d < 4; ++d) {
				int nx = dust.x + dx[d];
				int ny = dust.y + dy[d];
				if(isInArea(nx, ny) && map[nx][ny] != airCleaner) { // 영역안이고, 공청기아니면
					map[nx][ny] += spread; // 확산해주고
					cnt++; // 카운트
				}
			}
			map[dust.x][dust.y] -= (val/5) * cnt; 
		}
	}

	static boolean isInArea(int x, int y) {
		return 0 <= x && x < R && 0 <= y && y < C;
	}
}

 

 

 


 

집사는개발자가되고파

 

choppadontbiteme.tistory.com

 

반응형

'Algorithm > BOJ' 카테고리의 다른 글

[ BOJ ] 10820 문자열 분석 B2 (JAVA)  (0) 2021.08.07
[ BOJ ] 1009. 분산처리 B3 (JAVA)  (0) 2021.04.20
[ BOJ ] 17471. 게리맨더링 G5 JAVA  (0) 2021.04.16
[ BOJ ] 2564. 경비원 S1 JAVA  (0) 2021.04.16
[ BOJ ] 16562. 친구비 G3 JAVA  (0) 2021.04.15