mojo's Blog

[백준 16946] 벽 부수고 이동하기 4 본문

백준/Graph

[백준 16946] 벽 부수고 이동하기 4

_mojo_ 2021. 8. 26. 00:43

문제 링크 => 16946번: 벽 부수고 이동하기 4 (acmicpc.net)

 

16946번: 벽 부수고 이동하기 4

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이

www.acmicpc.net


그래프 탐색을 이용한 문제이다.

 

먼저 이동할 수 있는 지점(0으로 구성된 곳)에 대해서 값을 먼저 세팅하도록 하였다.

 

문제에 있는 예시 2로 설명하자면 다음과 같다.

 

4 5

11001

00111

01010

10101

 

이때, 1은 이동할 수 없는 지점(벽)이므로 0으로 세팅하고 0으로 된 지점에서 그 다음 0으로 이동할 수 있는지를 파악하도록 한다.

 

--- dp[N][M] ---

00220

33000

30101

01010

 

이때 같은 그룹임을 파악하기 위해서 visited 배열에서 방문 처리를 할 때, 1, 2, 3, ... 이런식으로 값을 다음과 같이 매겨주도록 하였다.

 

--- visited[N][M] ---

00110

22000

20304

05060

 

답을 구하기 위한 모든 세팅이 끝났다.

 

이제 dp, visited 배열을 통해서 벽인 지점에서 상하좌우 0인 지점에 대해서 dp 값을 더해주는데 같은 그룹을 두번 더하는 일이 없도록 visited 배열을 잘 활용하면 된다.

 

풀이 code

 

#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#define INF 100000000
#define endl '\n'
#define ll long long

using namespace std;

int dp[1001][1001];
int Map[1001][1001];
int dx[4] = { 1,-1,0,0 };
int dy[4] = { 0,0,1,-1 };
int visited[1001][1001];
int N, M, visitCnt;


void input() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		string s;
		cin >> s;
		for (int j = 0; j < M; j++) {
			Map[i][j] = s[j] - '0';
		}
	}
}

void setDp(int startX, int startY) {
	visitCnt++;
	int moveCnt = 1;
	queue<pair<int, int>> tmpQ;
	tmpQ.push({ startX,startY });
	queue<pair<int, int>> q;
	q.push({startX,startY});
	visited[startX][startY] = visitCnt;

	while (!q.empty()) {
		int x = q.front().first;
		int y = q.front().second;
		int cnt = q.front().second;
		q.pop();
		
		for (int i = 0; i < 4; i++) {
			int nextX = x + dx[i];
			int nextY = y + dy[i];
			if (nextX >= 0 && nextX < N && nextY >= 0 && nextY < M) {
				if (Map[nextX][nextY] == 0 && !visited[nextX][nextY]) {
					tmpQ.push({ nextX,nextY });
					moveCnt++;
					q.push({nextX,nextY});
					visited[nextX][nextY] = visitCnt;
				}
			}
		}
	}

	while (!tmpQ.empty()) {
		int x = tmpQ.front().first;
		int y = tmpQ.front().second;
		tmpQ.pop();
		dp[x][y] = moveCnt;
	}

}

void solve() {

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (Map[i][j] == 0 && !visited[i][j]) setDp(i, j);
		}
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (Map[i][j]) {
				map<int, int> m;
				dp[i][j] = 1;
				for (int k = 0; k < 4; k++) {
					int nextX = i + dx[k];
					int nextY = j + dy[k];
					if (nextX >= 0 && nextX < N && nextY >= 0 && nextY < M) {
						if (!Map[nextX][nextY] && !m[visited[nextX][nextY]]) {
							m[visited[nextX][nextY]] = 1;
							dp[i][j] += dp[nextX][nextY];
						}
					}
				}
			}
		}
	}

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			if (Map[i][j]) cout << dp[i][j] % 10;
			else cout << 0;
		}
		cout << endl;
	}

}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

	input();
	solve();

	return 0;
}

'백준 > Graph' 카테고리의 다른 글

[백준 1922] 네트워크 연결  (0) 2021.11.05
[백준 1916] 최소비용 구하기  (0) 2021.11.04
[백준 4803] 트리  (0) 2021.08.23
[백준 17412] 도시 왕복하기1  (0) 2021.08.18
[백준 6086] 최대 유량  (0) 2021.08.18
Comments