https://www.acmicpc.net/problem/16946
16946번: 벽 부수고 이동하기 4
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이
www.acmicpc.net
문제
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이 변을 공유할 때, 인접하다고 한다.
각각의 벽에 대해서 다음을 구해보려고 한다.
- 벽을 부수고 이동할 수 있는 곳으로 변경한다.
- 그 위치에서 이동할 수 있는 칸의 개수를 세어본다.
한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.
입력
첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다.
출력
맵의 형태로 정답을 출력한다. 원래 빈 칸인 곳은 0을 출력하고, 벽인 곳은 이동할 수 있는 칸의 개수를 10으로 나눈 나머지를 출력한다.
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int N, M;
int map[1001][1001];
int dx[4] = { 1,-1,0,0 };
int dy[4] = { 0,0,1,-1 };
bool visit[1001][1001];
void bfs(int row, int col)
{
queue<pair<int, int>> q;
vector<pair<int, int>> v;
q.push(make_pair(row,col));
visit[row][col] = true;
int result = 1;
while (!q.empty())
{
int nowX = q.front().first;
int nowY = q.front().second;
q.pop();
for (int i = 0; i < 4; i++)
{
int nextX = nowX + dx[i];
int nextY = nowY + dy[i];
if ((nextX < 0 || nextX >= N) || (nextY < 0 || nextY >= M))//범위 벗어나면 스킵
continue;
if (map[nextX][nextY] == 0 && visit[nextX][nextY] == false) //다음 칸이 방문한 적 없는 통로이면
{
q.push(make_pair(nextX, nextY));
visit[nextX][nextY] = true;
result++;
}
if (map[nextX][nextY] != 0 && visit[nextX][nextY] == false)//다음 칸이 방문한 적 없는 벽이라면
{
v.push_back(make_pair(nextX, nextY));
visit[nextX][nextY] = true;
}
}
}
for (int i = 0; i < v.size(); i++)
{
map[v[i].first][v[i].second] += result;
visit[v[i].first][v[i].second] = false;
}
}
int main()
{
//입력
cin >> N >> M;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
scanf("%1d", &map[i][j]); //공백이 없어도 숫자 하나씩만 입력받기
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
if (map[i][j] != 0)//현재칸이 통로가 아니면 스킵
continue;
if (visit[i][j])//현재칸이 0이지만 방문했다면 스킵
continue;
bfs(i, j); //0이고 방문안한 곳에서 bfs 실행
}
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
cout << map[i][j] % 10;
}
cout << '\n';
}
}
1. map을 탐색하며 0인 부분에서 bfs실행
2. bfs실행하여 상하좌우 탐색하며
2-1 => 0을 만났을 때 count++
2-2 => 1을 만났을 때 vector안에 벽 정보를 넣음
3. bfs함수가 끝날 때 bfs에서 탐색한 0들에 인접한 벽에 대해 (2-2에서 vector에 넣었던 벽들) 지금까지 count값을 더해준다.
'백준 c++ > (2-1)백준 c++ 알고리즘 중급' 카테고리의 다른 글
백준 16933 c++ 벽 부수고 이동하기 3 (0) | 2023.03.03 |
---|---|
백준 14442 c++ 벽 부수고 이동하기 2 (0) | 2023.02.19 |
백준 2206 c++ 벽 부수고 이동하기 (0) | 2023.02.11 |
백준 12886 c++ 돌 그룹 (0) | 2023.02.10 |
백준 14502 c++ 연구소 (0) | 2023.02.09 |