300x250

1. 제목

- 백준 16918 봄버맨

- BOJ 16918 봄버맨

문제 링크 : 16918번: 봄버맨 (acmicpc.net)

 

16918번: 봄버맨

첫째 줄에 R, C, N (1 ≤ R, C, N ≤ 200)이 주어진다. 둘째 줄부터 R개의 줄에 격자판의 초기 상태가 주어진다. 빈 칸은 '.'로, 폭탄은 'O'로 주어진다.

www.acmicpc.net


2. 풀이 과정

출력 결과에서는 .과 O로만 표시하고 있지만 해당 문제에서는 각 폭탄이 터지는 데까지 걸리는 시간이 있어요. 즉 맵에 O가 여러 개 표시되어 있더라도 각각 터지는 시간은 다를 수 있다는 거예요. 이러한 것을 저는 맵에 0은 빈칸 123은 각 폭탄이 설치되어 있는데 터지기까지 남은 시간을 표시했어요.

 

이문제는 각 폭탄들을 관리하는 것만 생각하면 쉽게 구현할 수 있는 문제였는데 매시간 맵을 검사해서 빈칸이 아닌 곳들은 전부 1씩 감소해주고 

맵을 검사했을 때 1인 부분은 폭탄이 터져야 하므로 벡터에 좌표를 다 넣어놓은 이후에 상하좌우를 0으로 바꿔서 빈칸으로 표시해 줬어요.

 

3. 폭탄 생성 

4. 폭탄 삭제

해당 행위가 반복이기 때문에 현재시간을 2로 나눠서 나머지에 폭탄 생성 함수와 폭발 함수를 번갈아 가면서 실행하게 구현해봤어요.

CreateBomb()을 보시면 폭탄을 새로 생성할 때 3초 후에 폭발하는 거로 표시하는데 처음의 Input()에서는 처음 폭탄을 2초 후에 폭발하는 거로 표시하고 있어요. 이거는

  • 다음 1초 동안 봄버맨은 아무것도 하지 않는다

라는 문항이 있기 때문에 미리 1씩 감소시켜서 맵에 표시해놨어요.


3. 코드

#include <iostream>
#include <vector>

#define Y first
#define X second

using namespace std;

int R, C, N;
int map[201][201];

// 상하좌우
int dy[4] = {1, -1, 0, 0};
int dx[4] = {0, 0, -1, 1};

void PrintMap()
{
	for (int y = 0; y < R; y++)
	{
		for (int x = 0; x < C; x++)
		{
			// 0인부분은 빈칸이므로 .으로 바꿔서 출력
			if (map[y][x] == 0)
				cout << ".";
			// 그외에 값은 전부 폭탄이므로 O으로 바꿔서 출력
			else
				cout << "O";
		}
		cout << endl;
	}
}

void Input()
{
	cin >> R >> C >> N;

	for (int y = 0; y < R; y++)
	{
		for (int x = 0; x < C; x++)
		{
			char c;
			cin >> c;
			if (c == '.')
				map[y][x] = 0;
			else
				map[y][x] = 2;
		}
	}
}

void Explosion()
{
	// 폭탄 좌표저장 벡터
	vector<pair<int, int>> v;

	for (int y = 0; y < R; y++)
	{
		for (int x = 0; x < C; x++)
		{
			if (map[y][x] == 1)
			{
				// 터지는 폭탄들 좌표 저장
				v.push_back({ y, x });
			}
		}
	}

	while (!v.empty())
	{
		pair<int, int> cur = v.back();
		v.pop_back();
		map[cur.Y][cur.X] = 0;
		for (int i = 0; i < 4; i++)
		{
			int ny = cur.Y + dy[i];
			int nx = cur.X + dx[i];

			if (ny <0 || nx <0 || ny> R || nx > C)
				continue;
			// 상하좌우 터져서 0(빈칸)으로 만들기
			map[ny][nx] = 0;
		}
	}
}

// 맵 전체를 검사한후 0인부분은 빈칸이므로 폭탄배치
void CreateBomb()
{
	for (int y = 0; y < R; y++)
	{
		for (int x = 0; x < C; x++)
		{
			if (map[y][x] == 0)
				map[y][x] = 3;
		}
	}
}


void Solution()
{
	// 현재시간 
	// 다음 1초 동안 봄버맨은 아무것도 하지 않는다. 그래서 1부터 시작
	int currentTime = 1;

	if (N == 1)
	{
		PrintMap();
		return;
	}
	while (true)
	{		
		// 폭탄이 설치되어 있지 않은 모든 칸에 폭탄을 설치한다.
		currentTime++;
		// 현재시간이 N초가 지났다면 종료
		if (currentTime > N)
			break;

		for (int y = 0; y < R; y++)
		{
			for (int x = 0; x < C; x++)
			{
				// 2~4은 폭탄을 의미한다.
				// 각 값 -1 은 폭탄이 터지기 까지 남은 시간을 의미
				if (map[y][x] > 1)
				{
					map[y][x] = map[y][x] - 1;
				}
			}
		}

		// 3과 4를 반복한다.
		// 3. 다음 1초 동안 폭탄이 설치되어 있지 않은 모든 칸에 폭탄을 설치한다. 즉, 모든 칸은 폭탄을 가지고 있게 된다. 폭탄은 모두 동시에 설치했다고 가정한다.
		if (currentTime % 2 == 0)
			CreateBomb();
		// 4. 1초가 지난 후에 3초 전에 설치된 폭탄이 모두 폭발한다.
		else
			Explosion();
	}
	PrintMap();
}

int main()
{
	Input();
	Solution();
	
	return 0;
}
300x250