티스토리 뷰

algorithm/problem solving

BOJ 17144 미세먼지 안녕!

무니웜테일패드풋프롱스 2020. 6. 28. 14:30

 

 

17144번: 미세먼지 안녕!

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

www.acmicpc.net

문제 설명에 나온대로 구현하면 되는 시뮬레이션 문제이다.

  • 확산: 4방향으로, 모든 미세먼지가 동시에 확산된다.
  • 정화: 공기청정기의 윗부분과 아랫부분의 바람의 방향에 따라서 미세먼지의 자리가 옮겨진다.

로직은 아래와 같다. 

  1.  BFS로 4방향 확산을 시켜준다. 여기서 확산시킨 미세먼지의 값은 변경해주되, 확산 된 미세먼지의 값은 다른 배열에 같은 위치에 저장(플러스) 해둔다.
  2. 모든 위치의 미세먼지의 확산이 끝났다면, 저장해둔 확산된 미세먼지를 각 위치에 더해준다.
  3. 공기청정기의 위치와 방향에 따라서 미세먼지의 위치를 변경시켜준다.
  4. 이를 T번 반복하면 된다.

가장 까다로웠던건 공기청정기 - 정화였다. 각 방향별로 미세먼지를 양옆 혹은 앞뒤로 옮겨주어야 하므로 x y 축을 잘 따져야한다. 

하지만 이도 그렇게 어려운 과정은 아니므로 크게 어려운 문제는 아니라고 생각한다. 

 

1. 미세먼지 확산 (BFS + spread ( 확산된 미세먼지 더해주기 ) ) 

private static int[][]dustMap;
	private static int[][]MapCopy;
	private static boolean[][]visited;
	static int[]dx = {-1,1,0,0};
	static int[]dy= {0,0,-1,1};
	private static Queue<pair>queue = new LinkedList<pair>();
	private static void bfs(int sx, int sy) { //확산
		// 네개의 방향으로 확산.
		// 확산 후, 확산시킨 곳의 미세먼지는 변경해준다.
		// 다른 곳의 미세먼지는 MapCopy의 해당 위치에 저장해둔다.
		visited[sx][sy]=true;
		queue.add(new pair(sx, sy)); 
		while(!queue.isEmpty()) {
			pair polled= queue.poll();
			int x = polled.x;
			int y = polled.y;
			int cnt = 0; 
			int dust = dustMap[x][y]/5;
			for(int i =0 ; i<4; i++) {
				int nx = x+dx[i];
				int ny = y+dy[i];
				if(nx<0 || ny<0 || nx>=R || ny>=C) continue;
				if(dustMap[nx][ny]==-1) continue;
				cnt++; //확산 시킨 칸의 수
				if(!visited[x][y]&&dustMap[nx][ny]!=0) {
					queue.add(new pair(nx,ny));
					visited[nx][ny]=true;
				}
				MapCopy[nx][ny]+=dust; // 확산
			}
			dustMap[x][y]=dustMap[x][y]-(dust*cnt); // 확산 후 변화 
		}
	}
	private static void spread() { // MapCopy에 있는 내용 옮기는 메서드
		for(int i =0 ; i<R; i++) {
			for(int j=0; j<C; j++) {
				dustMap[i][j]+=MapCopy[i][j];
			}
		}
	}

 

2. 정화 

	private static void move() { //공기청정기 가동 
		// 첫번째 공기청정기 위치 X1 0
		// 두번째 공기청정기 위치 X2 0
=
		dustMap[X1-1][0]=0;
		for(int i = X1-2 ; i>=0; i--) {
			dustMap[i+1][0]=dustMap[i][0];
		} 
		dustMap[0][0]=dustMap[0][1]; 
		for(int i = 1; i<C ; i++) {
			dustMap[0][i-1]=dustMap[0][i];
		} 
		dustMap[0][C-1]= dustMap[1][C-1];
		for(int i = 2; i<=X1; i++) {
			dustMap[i-1][C-1]=dustMap[i][C-1];
		}
		dustMap[X1][C-1]=dustMap[X1][C-2];
		for(int i= C-2; i > 1 ; i--) {
			dustMap[X1][i]=dustMap[X1][i-1];
		}
		dustMap[X1][1]=0;
		
		//두번째 공기청정기
		dustMap[X2+1][0]=dustMap[X2+2][0];
		for(int i = X2+2 ; i+1<R; i++) {
			dustMap[i][0]=dustMap[i+1][0];
		}  
		dustMap[R-1][0]=dustMap[R-1][1]; 
		for(int i = 1; i<C ; i++) {
			dustMap[R-1][i-1]=dustMap[R-1][i];
		} 
	
		dustMap[R-1][C-1]=dustMap[R-2][C-1];
		for(int i = R-3; i>=X2; i--) {
			dustMap[i+1][C-1]=dustMap[i][C-1];
		}
		dustMap[X2][C-1]=dustMap[X2][C-2];
		for(int i= C-2; i > 1 ; i--) {
			dustMap[X2][i]=dustMap[X2][i-1];
		}
		dustMap[X2][1]=0;
	}
	

 

 

전체 코드는 아래와 같다.

import java.io.*;
import java.util.*;
class pair{
	int x;
	int y;
	pair(int x, int y){
		this.x=x;
		this.y=y;
	}
}
public class Main {
	private static int R;
	private static int C;
	private static int T;
	private static int X1=-1; //공기청정기 1 의 위치 저장 
	private static int X2; // 공기청정기 2의 위치 저장 
	private static int[][]dustMap;
	private static int[][]MapCopy;
	private static boolean[][]visited;
	static int[]dx = {-1,1,0,0};
	static int[]dy= {0,0,-1,1};
	private static Queue<pair>queue = new LinkedList<pair>();
	private static void bfs(int sx, int sy) { //확산
		// 네개의 방향으로 확산.
		// 확산 후, 확산시킨 곳의 미세먼지는 변경해준다.
		// 다른 곳의 미세먼지는 MapCopy의 해당 위치에 저장해둔다.
		visited[sx][sy]=true;
		queue.add(new pair(sx, sy)); 
		while(!queue.isEmpty()) {
			pair polled= queue.poll();
			int x = polled.x;
			int y = polled.y;
			int cnt = 0; 
			int dust = dustMap[x][y]/5;
			for(int i =0 ; i<4; i++) {
				int nx = x+dx[i];
				int ny = y+dy[i];
				if(nx<0 || ny<0 || nx>=R || ny>=C) continue;
				if(dustMap[nx][ny]==-1) continue;
				cnt++; //확산 시킨 칸의 수
				if(!visited[x][y]&&dustMap[nx][ny]!=0) {
					queue.add(new pair(nx,ny));
					visited[nx][ny]=true;
				}
				MapCopy[nx][ny]+=dust; // 확산
			}
			dustMap[x][y]=dustMap[x][y]-(dust*cnt); // 확산 후 변화 
		}
	}
	
	private static void spread() { // MapCopy에 있는 내용 옮기는 메서드
		for(int i =0 ; i<R; i++) {
			for(int j=0; j<C; j++) {
				dustMap[i][j]+=MapCopy[i][j];
			}
		}
	}
	
	private static void move() { //공기청정기 가동 
		// 첫번째 공기청정기 위치 X1 0
		// 두번째 공기청정기 위치 X2 0
=
		dustMap[X1-1][0]=0;
		for(int i = X1-2 ; i>=0; i--) {
			dustMap[i+1][0]=dustMap[i][0];
		} 
		dustMap[0][0]=dustMap[0][1]; 
		for(int i = 1; i<C ; i++) {
			dustMap[0][i-1]=dustMap[0][i];
		} 
		dustMap[0][C-1]= dustMap[1][C-1];
		for(int i = 2; i<=X1; i++) {
			dustMap[i-1][C-1]=dustMap[i][C-1];
		}
		dustMap[X1][C-1]=dustMap[X1][C-2];
		for(int i= C-2; i > 1 ; i--) {
			dustMap[X1][i]=dustMap[X1][i-1];
		}
		dustMap[X1][1]=0;
		
		//두번째 공기청정기
		dustMap[X2+1][0]=dustMap[X2+2][0];
		for(int i = X2+2 ; i+1<R; i++) {
			dustMap[i][0]=dustMap[i+1][0];
		}  
		dustMap[R-1][0]=dustMap[R-1][1]; 
		for(int i = 1; i<C ; i++) {
			dustMap[R-1][i-1]=dustMap[R-1][i];
		} 
	
		dustMap[R-1][C-1]=dustMap[R-2][C-1];
		for(int i = R-3; i>=X2; i--) {
			dustMap[i+1][C-1]=dustMap[i][C-1];
		}
		dustMap[X2][C-1]=dustMap[X2][C-2];
		for(int i= C-2; i > 1 ; i--) {
			dustMap[X2][i]=dustMap[X2][i-1];
		}
		dustMap[X2][1]=0;
	}
	
	private static int getSum() { // 전체 미세먼지 수 반환 
		int sum = 0;
		for(int i =0 ; i< R; i ++) {
			for(int j=0; j<C; j++) {
				if(dustMap[i][j]==-1) continue;
				sum+=dustMap[i][j];
			}
		}
		return sum;
	}
	private static int solve() {
		for(int t =0 ; t<T; t++) {
			// 확산
			for(int i = 0 ; i <R; i++) {
				for(int j =0; j<C; j++) {
					if(dustMap[i][j]!=-1 && dustMap[i][j]!=0 && visited[i][j]!=true) {
						bfs(i,j);
					}
				}
			}
			spread(); 			
			move();
			
			//visited, copy 갱신
			for(int i=0; i< R; i++) {
				for(int j=0; j<C; j++) {
					MapCopy[i][j]=0;
					visited[i][j]=false;
				}
			}
		}
		return getSum();
	}
	
	public static void main(String[]args)throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		st = new StringTokenizer(br.readLine());
		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());	
		T = Integer.parseInt(st.nextToken());
		
		dustMap = new int[R][C];
		MapCopy = new int[R][C];
		visited = new boolean[R][C];
		String []s;
		for(int i = 0 ; i < R; i++) {
			s = br.readLine().split(" ");
			for(int j =0 ; j < C; j ++) {
				dustMap[i][j]=Integer.parseInt(s[j]);
				if(dustMap[i][j]==-1) {
					if(X1==-1) { X1= i; } // 공기청정기 1 
					else { X2 = i;} //공기청정기 2 
				}
			}
		}
		System.out.println(solve());
	}
}

'algorithm > problem solving' 카테고리의 다른 글

BOJ 14501 퇴사  (0) 2020.06.28
BOJ 1541 잃어버린 괄호  (0) 2020.06.17
BOJ 16234 인구이동  (0) 2020.06.17
BOJ 1976 여행 가자  (0) 2020.05.26
BOJ 2110 공유기 설치  (0) 2020.05.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
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
글 보관함