본문 바로가기
온라인 저지/BOJ

[BOJ/Java] 14502 연구소

by ahj 2022. 2. 18.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class BOJ14502 {

	static char[][] map;
	static int[][] delta = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
	static int n, m, cnt, max = 0;
	static LinkedList<int[]> virusInfo;

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		map = new char[n][m];
		virusInfo = new LinkedList<int[]>();
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < m; j++) {
				char tmp = st.nextToken().charAt(0);
				if (tmp == '2')
					virusInfo.add(new int[] { i, j });
				map[i][j] = tmp;
			}
		}
		br.close();
		// 8*8 지도에서 64C3해도 약 40000밖에 안되니까 충분히 돌릴만하다
		buildWall(0);
		// 입력 완료
		System.out.println(max);
	}

	// 2 입장에서 2 채워나가는 함수 짜기 call stack을 이용했기 때문에 dfs
	private static void spreadVirus(int r, int c) {
		// 기저조건
		if (map[r][c] == '1' || map[r][c] == '3' || map[r][c] == '4') {
			return;
		}
		// 0 이면 3으로 바꾸고
		// 2면 4로 바꾼다 restore 과정 때 기존의 것과 비교해줘야 함
		if (map[r][c] == '0') {
			map[r][c] = '3';
		}
		if (map[r][c] == '2') {
			map[r][c] = '4';
		}
		// 사방 탐색
		for (int i = 0; i < 4; i++) {
			int nR = r + delta[i][0];
			int nC = c + delta[i][1];
			if (nR >= 0 && nR < n && nC >= 0 && nC < m) {
				spreadVirus(nR, nC);
			}
		}
	}

	// 다음으로 넘어가야 하므로 다시 0으로 바꿔주기
	private static void restore() {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (map[i][j] == '3') {
					map[i][j] = '0';
				}
				if (map[i][j] == '4') {
					map[i][j] = '2';
				}
			}
		}
	}

	private static void buildWall(int builtCnt) {
		// 0중 3개를 1로 만들고서
		if (builtCnt == 3) {
			// 2가 퍼져나가는 형태일 때
			for (int[] vIndex : virusInfo) {
//				spreadVirus(vIndex[0], vIndex[1]);
				spreadVBFS(vIndex[0], vIndex[1]);
			}
			// 바이러스 다 퍼지고서 0개수 세어주기
			cnt = 0;
			// 쭉 돌면서 0count
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					if (map[i][j] == '0') {
						cnt++;
					}
				}
			}
			// max와 비교해가며 갱신
			if (cnt > max)
				max = cnt;
			restore();
			return;
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (map[i][j] == '0') {
					map[i][j] = '1';
					buildWall(builtCnt + 1);
					map[i][j] = '0';
				}
			}
		}
	}

	// 다시 queue를 이용해서 구현해보기
	private static void spreadVBFS(int r, int c) {
		LinkedList<int[]> q = new LinkedList<int[]>();
		q.offer(new int[] { r, c });

		while (!q.isEmpty()) {
			int[] cur = q.poll();

			for (int i = 0; i < 4; i++) {
				int nR = cur[0] + delta[i][0];
				int nC = cur[1] + delta[i][1];
				if (nR >= 0 && nR < n && nC >= 0 && nC < m) {
					if (map[nR][nC] == '0') {
						q.offer(new int[] { nR, nC });
						map[nR][nC] = '3';
					} else if (map[nR][nC] == '2') {
						map[nR][nC] = '4';
					}
				}
			}
		}
	}

}

시간 제한도 넉넉하고 array가 커봤자 8X8이길래 그냥 브루트 포스로 풀었다
분류랑 팀원들 푸신걸 보니까 바이러스 퍼뜨리는 코드를 BFS로 짤 수 있었는데... 생 각조차 못했다 또...ㅠ BFS도 연습하며 다시 적어봤다.

'온라인 저지 > BOJ' 카테고리의 다른 글

[BOJ/Java] 13300 방 배정  (0) 2022.02.20
[BOJ/Java] 10163 색종이  (0) 2022.02.20
[BOJ/Java] 9663 N-Queen  (0) 2022.02.18
[BOJ/Java] 1931 회의실 배정  (0) 2022.02.18
[BOJ/Java] 1987 알파벳  (0) 2022.02.18

댓글