오늘의 알고리즘
[C++] 백준 9328 열쇠
하늘하늘 .
2022. 12. 4. 01:16
#include <iostream>
#include <string.h>
#include <string>
#include <queue>
int h = 0;
int w = 0;
int ans = 0;
char Floor[102][102] = {};
bool visit[102][102] = {};
bool key[26] = {};
int dx[4] = { 0, 0, 1, -1 };
int dy[4] = { 1, -1, 0, 0 };
std::string alreadyKey = {};
void BFS(int row, int col)
{
std::queue<std::pair<int, int>> que = {};
std::queue<std::pair<int, int>> door[26] = {};
que.push({ row, col });
visit[row][col] = true;
while (!que.empty())
{
int x = que.front().first;
int y = que.front().second;
que.pop();
for (int i = 0; i < 4; ++i)
{
int nextX = x + dx[i];
int nextY = y + dy[i];
if (nextX >= 0 && nextY >= 0 && nextX <= h + 1 && nextY <= w + 1)
{
if (Floor[nextX][nextY] == '*' || visit[nextX][nextY])
continue;
visit[nextX][nextY] = true;
if ('A' <= Floor[nextX][nextY] && Floor[nextX][nextY] <= 'Z')
{
if (key[Floor[nextX][nextY] - 'A'])
{
que.push({ nextX, nextY });
}
else
{
door[Floor[nextX][nextY] - 'A'].push({ nextX, nextY });
}
}
else if ('a' <= Floor[nextX][nextY] && Floor[nextX][nextY] <= 'z')
{
que.push({ nextX, nextY });
if (!key[Floor[nextX][nextY] - 'a'])
{
key[Floor[nextX][nextY] - 'a'] = true;
while (!door[Floor[nextX][nextY] - 'a'].empty())
{
que.push(door[Floor[nextX][nextY] - 'a'].front());
door[Floor[nextX][nextY] - 'a'].pop();
}
}
}
else
{
que.push({ nextX, nextY });
if (Floor[nextX][nextY] == '$')
++ans;
}
}
}
}
}
int main(void)
{
int t = 0;
std::cin >> t;
while (t--)
{
memset(Floor, 0, sizeof(Floor));
memset(visit, false, sizeof(visit));
memset(key, false, sizeof(key));
alreadyKey.clear();
ans = 0;
std::cin >> h >> w;
for (int i = 1; i <= h; ++i)
{
for (int j = 1; j <= w; ++j)
{
std::cin >> Floor[i][j];
}
}
std::cin >> alreadyKey;
for (int i = 0; i < alreadyKey.size(); ++i)
{
if (alreadyKey[i] == '0')
continue;
key[alreadyKey[i] - 'a'] = true;
}
BFS(0, 0);
std::cout << ans << "\n";
}
return 0;
}
변형적인 넓이탐색 문제입니다.
1. 무조건 바깥에서 들어갈 수 있습니다 > 칸 수를 하나 더 늘려서 0,0에서 BFS를 시작하면 모든 바깥쪽에서 입장이 가능
2. 열쇠가 있어야 들어갈 수 있습니다 > 문을 만났을 경우 열쇠가 없다면 기존 큐가 아닌 새로운 큐에 저장해놓고 열쇠를 찾았을 경우 새로운 큐에 있는 위치를 기존 큐에 입력합니다. > 열쇠가 있든 없든 위치를 기억해놓고 푸는 겁니다.