PS/문제

BOJ. G2 모래성

코어른(진) 2025. 2. 5. 05:23

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

 

Brute하게는 100만개의 8방을 매번 검사하여 찾을 수 있다.

하지만 모래성이 하나하나 꺼지는 경우를 생각하면, 시간복잡도에서 뻑이 날 것이다.

따라서, 이를 줄이는 부분이 필요하고, 모래성이 꺼질 때만 그 주변의 모래성을 검사하면 된다는 아이디어로 최적화를 할 수 있었다.

 

BFS와 Level Queue 테크닉을 사용하여 문제를 해결했다.

 

#include <bits/stdc++.h>
#define fastio std::ios_base::sync_with_stdio(false);\
cin.tie(NULL)
using namespace std;

using ll = long long;
using pii = pair<int, int>;
using tiii = tuple<int, int, int>;

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

const int INF = 0x3f3f3f3f;

// HW 가 1000
// 100만 개를 매번 조사하기에는...
// Q2개를 이용해 후보를 넣는식?

// .을 돌면서 보드하나 생성
// 전체 보드를 돌면서 부서진 부분 Q에 넣어줌
// 부서진 부분에서 8방에 대해 +1
// 8방중 +할 때, 자기 자신보다 커진 부분에 대해 다시 Q에 넣어주고 Mark

int H, W;
int Board[1000][1000];
int Cnt[1000][1000];

const int Mark = 10000;

bool OOB(int y, int x)
{
	return  y <0 || x < 0 || y >= H || x >= W;
}

int main()
{
	fastio;

	cin >> H >> W;

	for(int i = 0; i < H; ++i)
	{
		string str;
		cin >> str;
		for(int j = 0; j < str.size(); ++j)
		{
			if(str[j] == '.')
			{
				Board[i][j] = INF;
			}
			else
			{
				Board[i][j] = str[j] - '0';
			}
		}
	}

	queue<pii> Q;
	for(int i = 0; i < H; ++i)
	{
		for(int j = 0; j < W; ++j)
		{
			if(Board[i][j] != INF)
			{
				continue;
			}
			
			for(int n = 0; n < 3; ++n)
			{
				int ny = i + dy[n];
				for(int m = 0; m < 3; ++m)
				{
					if(n == 0 && m == 0)
					{
						continue;
					}
					
					int nx = j + dx[m];
					if(OOB(ny, nx))
					{
						continue;
					}
					
					++Cnt[ny][nx];
					if(Cnt[ny][nx] >= Board[ny][nx])
					{
						if(Board[ny][nx] != Mark)
						{
							Q.push({ny, nx});
							Board[ny][nx] = Mark;	
						}
					}
				}
			}
		}
	}

	int Wave = 0;

	while(!Q.empty())
	{
		int Qsz = Q.size();
		++Wave;
		while(Qsz--)
		{
			auto [cy, cx] = Q.front();
			Q.pop();

			Board[cy][cx] = INF;

			for(int n = 0; n < 3; ++n)
			{
				int ny = cy + dy[n];
				for(int m = 0; m < 3; ++m)
				{
					if(n == 0 && m == 0)
					{
						continue;
					}
					
					int nx = cx + dx[m];
					if(OOB(ny, nx))
					{
						continue;
					}

					++Cnt[ny][nx];
					if(Cnt[ny][nx] >= Board[ny][nx])
					{
						if(Board[ny][nx] != Mark)
						{
							Q.push({ny, nx});
							Board[ny][nx] = Mark;	
						}
					}
				}
			}
		}
	}

	cout << Wave;
	
	return 0;
}


// S : 447
// U : 448 
// T : 454 
// C : 517
// Total : 30min