0. 개요

https://www.acmicpc.net/problem/16920
문제 원 출처 링크

해당 문제로 queue의 다양한 활용을 확인할 수 있다.

1. 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#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'만큼 확산되는 형태