백준/DFS BFS

[백준 2573번 / C++] 빙산

배발자 2022. 3. 14.
반응형

이 문제는 bfs를 활용해서 풀면 된다. 

 

#접근방법 

 

bfs를 적용한 문제를 얼마나 많이 풀어봤냐에 따라서 해당 문제가 쉽게 느껴질 수 있고 어렵게 느껴질 수 있을거라고 생각한다. 

 

  1. 빙산의 크기 map에 담고 map크기 만큼 temp라는 이차원배열을 생성한다. ( 갱신된 내용 temp에 저장.) 
  2. 빙산 주변에 인접한 0의 개수(바다) 만큼 map의 값에서 빼준 후 결과 값을 temp 에 넣어준다. 
  3. temp 이차원 배열에는 갱신된 내용이 담겨져 있고 해당 데이터를 토대로 덩어리를 계산해준다. 
  4. 즉, bfs를 호출한 개수가 덩어리 개수이다. ( bfs는 서로 인접한 데이터에 값이 있으면 퍼지면서 탐색 하기 때문) 
  5. 덩어리의 개수가 2개 이상이 아니면 다시 2번부터 반복한다. 

 

 

#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>
#include <cstring>
using namespace std; 
int m, n;
int map[300][300]; 
int visited[300][300]; 
int temp[300][300]; 
int result; 
int dx[4] = { 0,0,-1,1 }; 
int dy[4] = { 1,-1,0,0 }; 
queue <pair<int, int>> q; 
void bfs() {
	//연결되어있는 빙산 visited체크 하기. 
	while (!q.empty()) {
		int y, x; 
		tie(y, x) = q.front(); 
		q.pop(); 
		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i]; 
			int ny = y + dy[i]; 
			if (nx < 0 || nx >= n || ny < 0 || ny >= m)continue;
			if (temp[ny][nx] == 0 || visited[ny][nx] == 1)continue; 
			visited[ny][nx] = 1; 
			q.push({ ny,nx }); 
		}
	}
}
void check() {
	result++; 
	//녹일 빙산 계산 해서 temp에 담기 
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (map[i][j]) {
				int cnt = 0; 
				for (int k = 0; k < 4; k++) {
					int nx = j + dx[k]; 
					int ny = i + dy[k]; 
					if (nx < 0 || nx >= n || ny < 0 || ny >= m)continue; 
					if (map[ny][nx] == 0)cnt++; 
				}
				int res = map[i][j] - cnt; 
				if (res <= 0)temp[i][j] = 0;
				else temp[i][j] = res; 
			}
		}
	}
	int cnt = 0; 
	//덩어리 계산
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (temp[i][j]&&visited[i][j]==0) {
				visited[i][j] = 1; 
				q.push({ i, j });
				cnt++; 
				bfs(); 
			}
		}
	}
	//덩어리가 2개 이상이면 종료.
	if (cnt >= 2) {
		cout << result; 
		exit(0); 
	}
	else {
		bool c = false; 
		//temp값을 map에 저장. 
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				map[i][j]= temp[i][j] ;
				if (temp[i][j])c = true; 
			}
		}
		//map이 모두 0이면 0출력 및 종료
		if (!c) {
			cout << 0; 
			exit(0); 
		}
		//초기화 
		memset(temp, 0, sizeof(temp)); 
		memset(visited, 0, sizeof(visited)); 
		check(); 
	}
}

int main() {
	ios::sync_with_stdio(0); 
	cin.tie(0); 
	cout.tie(0); 
	cin >> m >> n; 
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			cin >> map[i][j]; 
		}
	}
	check(); 
	
}
 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

반응형

댓글