알고리즘 문제

[백준] 2573번 빙산

feelcoding 2021. 1. 21. 22:55
728x90

www.acmicpc.net/problem/2573

 

2573번: 빙산

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

www.acmicpc.net

BFS로 풀었다. 일단 빙산을 녹인 후 몇 덩이인지 BFS로 알아보았다. 빙산의 개수가 한 덩이가 아니거나 빙산이 모두 녹았으면 반복문을 빠져나가게 했다.

#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;

int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };

int main() {
	cin.tie(NULL);
	ios::sync_with_stdio(false);
	int n, m;
	cin >> n >> m;
	vector<vector<int>> v(n, vector<int>(m));
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> v[i][j];
			if (v[i][j] != 0) {
				cnt++;
			}
		}
	}
	int answer = 0;
	int year = 0;
	int isSplited = false;
	while (true) {
    	// 빙산 녹이기
		vector<vector<int>> temp = v;
		for (int i = 1; i < n - 1; i++) {
			for (int j = 1; j < m - 1; j++) {
				int zeroCount = 0;
				if (v[i][j] != 0) {
					for (int k = 0; k < 4; k++) {
						int row = i + dx[k];
						int col = j + dy[k];
						if (v[row][col] == 0) {
							zeroCount++;
						}
					}
					temp[i][j] -= zeroCount;
					if (temp[i][j] < 0)
						temp[i][j] = 0;
				}
			}
		}
		v = temp;
        
        // 한 덩이인지 체크하기 위한 BFS (너비우선탐색)
		vector<vector<bool>> visited(n, vector<bool>(m));
		bool out = false;
		for (int i = 1; i < n - 1; i++) {
			for (int j = 1; j < m - 1; j++) {
				if (v[i][j] != 0) { // 이 if문에 들어가서 탐색만 하면 탐색을 끝낸다.
					queue<pair<int, int>> q;
					q.push(make_pair(i, j));
					while (!q.empty()) {
						pair<int, int> cur = q.front();
						q.pop();
						if (!visited[cur.first][cur.second]) {
							visited[cur.first][cur.second] = true;
							for (int i = 0; i < 4; i++) {
								int row = cur.first + dx[i];
								int col = cur.second + dy[i];
								if (v[row][col] != 0) {
									q.push(make_pair(row, col));
								}
							}
						}
					}
					out = true;
					break;
				}
				if (out)
					break;
			}
			if (out)
				break;
		}
		for (int r = 1; r < n - 1; r++) {
			for (int c = 1; c < m - 1; c++) {
				if (v[r][c] != 0 && !visited[r][c]) { // 방문하지 않은 빙산이 있다면
					isSplited = true; // 두 덩어리 이상으로 쪼개졌다는 뜻이다.
					break;
				}
			}
			if (isSplited)
				break;
		}
		year++;
		if (isSplited)
			break;
		bool flag = true;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (v[i][j] != 0) {
					flag = false;
					break;
				}
			}
			if (!flag)
				break;
		}
		if (flag) { // 모두 녹아 빙산이 하나도 없다면 빠져나간다
			break;
		}
	}
	if (!isSplited) {
		cout << 0;
	}
	else cout << year;
	return 0;
}
728x90