본문 바로가기
Problem Solving/백준

백준 2234 : 성곽

by Libi 2021. 8. 30.
반응형

https://www.acmicpc.net/problem/2234

 

2234번: 성곽

첫째 줄에 두 정수 n, m이 주어진다. 다음 m개의 줄에는 n개의 정수로 벽에 대한 정보가 주어진다. 벽에 대한 정보는 한 정수로 주어지는데, 서쪽에 벽이 있을 때는 1을, 북쪽에 벽이 있을 때는 2를,

www.acmicpc.net

[ 문제풀이 ]

서북동남 순서로 1,2,4,8의 값을 가지기 때문에 (1~4)번째 bit가 1인지를 확인해주면 벽이 존재하는지 판단할 수 있다.

따라서 dfs + 비트마스킹을 통해 탐색하면서 방마다 인덱스를 매겨주고 각 방의 넓이를 저장해준다. 이렇게 하면 1, 2번을 해결할 수 있다.

3번을 해결하기 위해서 벽을 제거하였는지를 판단하는 변수를 하나 두고 dfs를 수행해도 되지만 어차피 벽들은 붙어있기 때문에 모든 좌표를 탐색하면서 현재 방에서 인접한 방 중 가장 넓은 방의 인덱스를 저장해주면 해결할 수 있다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

public class Main {

	static int n, m, idx, cnt;
	static List<Integer> area;
	static int[][] map, visit;
	static int[][] dir = {{0,-1},{-1,0},{0,1},{1,0}};
	
	public static void main(String[] args) {
		try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
				BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			n = Integer.parseInt(st.nextToken());
			m = Integer.parseInt(st.nextToken());
			map = new int[m][n];
			visit = new int[m][n];
			for (int i = 0; i < m; ++i) {
				st = new StringTokenizer(br.readLine());
				for (int j = 0; j < n; ++j) {
					map[i][j] = Integer.parseInt(st.nextToken());
				}
			}
			
			area = new ArrayList<>(Arrays.asList(0));
            		//dfs를 수행하면서 방에 번호를 매겨줌
			for (int i = 0; i < m; ++i) {
				for (int j = 0; j < n; ++j) {
					if (visit[i][j] != 0) continue;
					idx++; cnt = 0;
					dfs(i, j);
					area.add(cnt);
				}
			}
			
            		//모든 좌표를 탐색하면서 인접한 방 중 가장 넓은 방의 크기를 저장
			int[] near = new int[idx + 1];
			for (int i = 0; i < m; ++i) {
				for (int j = 0; j < n; ++j) {
					for (int d = 0; d < 4; ++d) {
						int ny = i + dir[d][0];
						int nx = j + dir[d][1];
						if (ny < 0 || nx < 0 || ny >= m || nx >= n) continue;
						if (visit[ny][nx] == visit[i][j]) continue;
						near[visit[i][j]] = Math.max(near[visit[i][j]], area.get(visit[ny][nx]));
					}
				}
			}
			
			int maxArea1 = 0, maxArea2 = 0;
			for (int i = 1; i <= idx; ++i) {
				maxArea1 = Math.max(maxArea1, area.get(i));
				maxArea2 = Math.max(maxArea2, area.get(i) + near[i]);
			}
			bw.write(idx + "\n" + maxArea1 + "\n" + maxArea2 + "\n");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void dfs(int y, int x) {
		cnt++;
		visit[y][x] = idx;
		for (int d = 0; d < 4; ++d) {
			if (((map[y][x] >> d) & 1) == 1) continue;
			int ny = y + dir[d][0];
			int nx = x + dir[d][1];
			if (ny < 0 || nx < 0 || ny >= m || nx >= n) continue;
			if (visit[ny][nx] != 0) continue;
			dfs(ny, nx);
		}
	}
}

 

 

반응형

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

백준 9470 : Strahler 순서  (0) 2021.09.04
백준 1029 : 그림 교환  (0) 2021.08.31
백준 5624 : 좋은 수  (0) 2021.08.29
백준 5214 : 환승  (0) 2021.08.27
백준 1826 : 연료 채우기  (0) 2021.08.26

댓글