Algorithm/백준

백준 - 미세먼지 안녕!

whyWhale 2023. 3. 13.

문제 설명

주의사항

여기에서 확산할 때, 원본을 유지한 상태에서 확산이 이루어져야 한다.

왜냐하면 다음 대상에는 이미 영향을 받았기 때문에 영향받은 값에서 확산이 또일어난다면 정답과 멀어지기 때문이다.

풀이

public class DustHello {
	static int map[][];
	static int n, m;
	private static List<Node> cleaner;

	public static void main(String[] args) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

		StringTokenizer st = new StringTokenizer(reader.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		int t = Integer.parseInt(st.nextToken());

		map = new int[n][m];
		cleaner = new ArrayList<>();
		// 격자 구성
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(reader.readLine());
			for (int j = 0; j < m; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());

				if (map[i][j] == -1) {
					cleaner.add(new Node(i, j));
				}
			}
		}

		while (t-- > 0) {
			// 1. 미세먼지 확산 map[r][c]/5 그리고 map[r][c] - (map[r][c]/5 * 방향 수)
			spread();
			//  2. 공기청정기 작동 (반시계 방향 and 시계방향
			clean();
		}

		// 3. t초가 지난후 미세먼지의 총양 구하기
		int answer = Arrays.stream(map).flatMapToInt(Arrays::stream).sum();
		System.out.println(answer+2);
	}

	private static void clean() {
		Node top = cleaner.get(0);

		for (int i = top.y - 1; i > 0; i--) {
			map[i][top.x] = map[i - 1][top.x];
		}

		for (int i = top.x; i < m - 1; i++) {
			map[0][i] = map[0][i + 1];
		}

		for (int i = 0; i < top.y; i++) {
			map[i][m - 1] = map[i + 1][m - 1];
		}

		for (int i = m - 1; i > top.x + 1; i--) {
			map[top.y][i] = map[top.y][i - 1];
		}

		map[top.y][top.x + 1] = 0;

		Node bottom = cleaner.get(1);

		for (int i = bottom.y + 1; i < n - 1; i++) {
			map[i][bottom.x] = map[i + 1][bottom.x];
		}

		for (int i = bottom.x; i < m - 1; i++) {
			map[n - 1][i] = map[n - 1][i + 1];
		}

		for (int i = n - 1; i > bottom.y; i--) {
			map[i][m - 1] = map[i - 1][m - 1];
		}

		for (int i = m - 1; i > bottom.x + 1; i--) {
			map[bottom.y][i] = map[bottom.y][i - 1];
		}

		map[bottom.y][bottom.x + 1] = 0;
	}

	static class Node {
		int y, x;

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

	static int dy[] = {-1, 1, 0, 0};
	static int dx[] = {0, 0, -1, 1};

	public static void spread() {
		// 미세먼지 찾기
		LinkedList<Node> dusts = new LinkedList<>();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (map[i][j] == -1 || map[i][j] == 0) // 청소기 and 빈칸
					continue;

				dusts.offer(new Node(i, j));
			}
		}

		// 확산 - map[r][c]/5 그리고 map[r][c] - (map[r][c]/5 * 방향 수)
		int[][] cpMap = new int[n][m];

		for (int i = 0; i < n; i++) {
			cpMap[i] = map[i].clone(); // 원본 더스트 필요
		}
		while (!dusts.isEmpty()) {
			Node cur = dusts.poll();
			// map[ny][nx]대로 하면 이미 이전 노드들로 영향받은 것까지 더하게 되는 이슈가 있음.
			int amount = cpMap[cur.y][cur.x] / 5;

			if (amount == 0) // 확산할 양 0이면 방향 탐색 필요없음
				continue;

			int cnt = 0;

			// 주변 확산
			for (int i = 0; i < 4; i++) {
				int ny = cur.y + dy[i];
				int nx = cur.x + dx[i];

				if (isOutOfRange(ny, nx))
					continue;
				if (map[ny][nx] == -1) // 공기 청정기
					continue;

				cnt++;
				map[ny][nx] += amount;
			}

			map[cur.y][cur.x] -= amount * cnt;
		}

	}

	public static boolean isOutOfRange(int ny, int nx) {
		return ny < 0 || nx < 0 || ny >= n || nx >= m;
	}
}

'Algorithm > 백준' 카테고리의 다른 글

백준 - 마법사 상어와 파이어볼  (1) 2023.03.14
백준 - 단절점과 단절선  (0) 2023.03.14
마법사 상어와 비바라기  (1) 2023.03.12
중앙값 구하기  (0) 2023.03.11
데이터 체커  (0) 2023.03.09

댓글