Skip to content
boj-16920.md 3.02 KiB
Newer Older
hoon's avatar
hoon committed
---
layout    : wiki
title     : BOJ 16920. 확장 게임
summary   : 
date      : 2019-04-14 23:01:01 +0900
updated   : 2021-12-15 17:58:46 +0900
tag       : bfs
public    : true
published : true
parent    : [[boj]]
latex     : false
hoon's avatar
hoon committed
---
* TOC
{:toc}
hoon's avatar
hoon committed

## 0. 개요
<https://www.acmicpc.net/problem/16920>  
[문제 원 출처 링크](https://codeforces.com/contest/1105/problem/D )
hoon's avatar
hoon committed

해당 문제로 queue의 다양한 활용을 확인할 수 있다.
hoon's avatar
hoon committed


## 1. 코드

hoon's avatar
hoon committed
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <cstdlib>
#include <map>

using namespace std;

void printBoard();
void printVisit();

#define MAX_N 1010
#define MAX_P 12
#define EMPTY '.'
#define WALL '#' 

int N, M, P;
char board[MAX_N][MAX_N];
int isVisited[MAX_N][MAX_N];
int range[MAX_P];

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

queue<pair<int, int> > q[MAX_P];

int bfs()
{
	queue<int> playerQ;
	for (int i = 1; i <= P; i++)
		playerQ.push(i);
	
	while (!playerQ.empty())
	{
		int i = playerQ.front();
		playerQ.pop();

		int rCnt = range[i];
		while (!q[i].empty() && rCnt--)
		{
			int qSize = q[i].size();
			for (int qs = 0; qs < qSize; qs++)
			{
				int r = q[i].front().first;
				int c = q[i].front().second;
				q[i].pop();

				for (int j = 0; j < 4; j++)
				{
					int nr = r + dx[j];
					int nc = c + dy[j];
					if (nr < 0 || nr >= N || nc < 0 || nc >= M || isVisited[nr][nc] != 0)
						continue;

					isVisited[nr][nc] = i;
					q[i].push({ nr, nc });
				}
			}
		}
		if (q[i].size() > 0)
			playerQ.push(i);
	}
	return 0;
}

int main()
{
//	freopen("in.txt", "r", stdin);

	int testcase = 1;
//	scanf("%d", &testcase);
	for (int tc = 1; tc <= testcase; tc++)
	{
		memset(isVisited, 0, sizeof(isVisited));

		scanf("%d%d%d", &N, &M, &P);
		for (int i = 1; i <= P; i++)
			scanf("%d", &range[i]);
		for (int i = 0; i < N; i++)
		{
			scanf("%s", &board[i]);
			for (int j = 0; j < M; j++)
			{
				if (board[i][j] != EMPTY && board[i][j] != WALL)
				{
					int idx = board[i][j] - '0';
					q[idx].push({ i, j });
					isVisited[i][j] = idx;
				}
				else if (board[i][j] == WALL)
					isVisited[i][j] = -1;
			}
		}

		bfs();

		int res[MAX_P] = { 0, };
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < M; j++)
			{
				if (isVisited[i][j] <= 0)
					continue;
				res[isVisited[i][j]]++;
			}
		}
		for (int i = 1; i <= P; i++)
			printf("%d ", res[i]);
		printf("\n");
	}
}

void printBoard()
{
	for (int i = 0; i < N; i++)
		printf("%s\n", board[i]);
	printf("\n");
}
void printVisit()
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < M; j++)
		{
			if (board[i][j] == WALL)
				printf("%c", board[i][j]);
			else
				printf("%d", isVisited[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}
```


## 2. 풀이

1. player 수 만큼의 queue가 필요
2. 각 player에 해당하는 queue들이 비어 있지 않으면 playerQ에 저장된다.
3. 'S칸 만큼 이동할 수 있는 모든 칸에 성을 동시에 만든다.' -> bfs에서 count 'S'만큼 확산되는 형태