파핑파핑 지뢰찾기


SW Expert Academy [1868] 파핑파핑 지뢰찾기

문제보기
Alt text

풀이

  • aroundChk() : 8면에 지뢰가 있는지 확인하고 지뢰가 없으면 큐에 담고, 있으면 지뢰 갯수를 memo 배열에 저장
  • cntPoping() : aroundChk()를 통해 큐에 담겨진 것이 이전에 poping 되면 중복되므로 잘 체크하고, memo에서 0으로 기록된 곳은 다시 방문

    소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
	static int N, ans, dotCnt;
	static char[][] map;
	static int[][] memo;
	static Queue<int[]> poping;
	static int[] dx = { 0, 0, -1, 1, -1, -1, 1, 1 };
	static int[] dy = { -1, 1, 0, 0, -1, 1, -1, 1 };

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());

		for (int tc = 1; tc <= T; tc++) {
			N = Integer.parseInt(br.readLine());
			map = new char[N][N];
			memo = new int[N][N];
			dotCnt = 0;

			for (int i = 0; i < N; i++) {
				String str = br.readLine();
				for (int j = 0; j < N; j++) {
					map[i][j] = str.charAt(j);
					if (map[i][j] == '.')
						dotCnt++;
				}
			}

			ans = 0;
			Queue<int[]> q = aroundChk();
			if (q.size() > 0) {
				poping = new LinkedList<>();
				cntPoping(q, false);
				ans += dotCnt;
			} else
				ans = dotCnt;
			System.out.println("#" + tc + " " + ans);
		}
	}

	static Queue<int[]> aroundChk() {
		Queue<int[]> queue = new LinkedList<>();
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (map[i][j] == '*')
					continue;
				boolean flag = false;
				int idx = 0;
				int cnt = 0;
				while (idx < 8) {
					int x = i + dx[idx];
					int y = j + dy[idx];
					if (isRange(x, y) && map[x][y] == '*') {
						flag = true;
						cnt++;
					}
					idx++;
				}
				if (!flag) {
					queue.add(new int[] { i, j });
				}
				memo[i][j] = cnt;
			}
		}
		return queue;
	}

	static void cntPoping(Queue<int[]> q, boolean flag) {
		while (!q.isEmpty() && dotCnt > 0) {
			int[] point = q.poll();
			if (map[point[0]][point[1]] != '.') // 숫자로 바뀐경우
				continue;
			dotCnt--;
			if (!flag)
				ans++;
			map[point[0]][point[1]] = '0';
			for (int k = 0; k < 8; k++) {
				int x = point[0] + dx[k];
				int y = point[1] + dy[k];
				if (isRange(x, y) && map[x][y] == '.') {
					if (memo[x][y] == 0)
						poping.add(new int[] { x, y });
					else {
						map[x][y] = Character.forDigit(memo[x][y], 10);
						dotCnt--;
					}
				}
			}

			while (!poping.isEmpty()) {
				cntPoping(poping, true);
			}
		}
	}

	static boolean isRange(int x, int y) {
		return x >= 0 && y >= 0 && x < N && y < N;
	}
}