PS

[백준] 2234번 성곽 (C++)

-minari- 2024. 9. 21. 16:52

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

 

문제 설명

 

m*n 형태의 숫자를 입력을 받는다.

각 숫자는 0에서 15 사이의 숫자로 구성되어 있고, 이 숫자는 벽의 위치를 나타낸다.

서쪽에 벽이 있을때 1, 북쪽 에 벽이 있을때 2, 동쪽 에 벽이 있을때 4, 남쪽 에 벽이 있을때 8이 더해져있다.

이 성에 있는 방의 개수, 가장 넓은 방의 크기, 하나 벽을 제거하여 얻을 수 있는 가장 넓은 방의 크기를 구하면 된다.

주요 로

1. dfs를 사용해 방의 개수와 각 방의 넓이를 구한다.

-> 입력 받은 숫자를 비트마스킹을 통해 벽이 있는 곳은 탐색하지 못하도록 구현한다. 

2. 벽 하나를 제거했을 때 얻을 수 있는 가장 넓은 방의 크기를 찾는다.

-> visited[][] 배열에 단순히 1,0 으로 방문 여부를 표현하는 것이 아니라 방별로 다른 수를 부여해 완전탐색을 통해 제거할 벽을 찾는다.

정답 코드

 

#include <bits/stdc++.h>

using namespace std;

int n,m,cnt;
int arr[53][53], visited[53][53];
int dy[4] = {0,-1,0,1}, dx[4] = {-1,0,1,0};
vector<int> v, v_mx;

int dfs(int y, int x){
	int ret = 1;
	visited[y][x] = cnt;
	for(int i=0; i<4; i++){
		int ny = y + dy[i];
		int nx = x + dx[i];
		if(ny < 0 || nx < 0 || ny >= n || nx >= m) continue;
		if(visited[ny][nx]) continue;
		if(arr[y][x] & (1<<i)) continue;
		ret += dfs(ny,nx);
	}
	return ret;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	
	cin >> m >> n;
	for(int i=0; i<n; i++){
		for(int j=0; j<m; j++){
			cin >> arr[i][j];
		}
	}
	
	for(int i=0; i<n; i++){
		for(int j=0; j<m; j++){
			if(visited[i][j] == false){
				cnt++;
				int val = dfs(i,j);
				v.push_back(val);
			}
		}
	}
	
	for(int i=0; i<n; i++){
		for(int j=0; j<m-1; j++){
			if(visited[i][j] != visited[i][j+1]){
				int cnt = v[visited[i][j]-1] + v[visited[i][j+1]-1];
				v_mx.push_back(cnt);
			}
		}
	}
		
	for(int i=0; i<m; i++){
		for(int j=0; j<n-1; j++){
			if(visited[j][i] != visited[j+1][i]){
				int cnt = v[visited[j][i]-1] + v[visited[j+1][i]-1];
				v_mx.push_back(cnt);
			}
		}
	}

	sort(v.begin(), v.end());
	sort(v_mx.begin(), v_mx.end());
	cout << v.size() << "\n" << v[v.size()-1] << "\n";
	cout << v_mx[v_mx.size()-1] << "\n";
	return 0;
}