※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 25307번 문제인 시루의 백화점 구경이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/25307 

 

25307번: 시루의 백화점 구경

첫째 줄에 백화점의 세로 길이, 가로 길이, 마네킹과 떨어져야 하는 거리를 의미하는 정수 $N, M, K$가 공백으로 구분되어 주어진다. ($1 \leq N,M \leq 2\,000$, $0 \leq K \leq 4\,000$) 둘째 줄부터 $N$개의 줄

www.acmicpc.net

먼저, 시루가 접근할 수 없는 칸이 어디어디인지를 모두 알고 있다면 이 문제는 단순한 bfs문제와 같은 방식으로 해결할 수 있게 된다. 시루가 접근할 수 없는 칸은 1) 벽이거나 2) 택시거리가 K 이하인 칸에 마네킹이 존재하는 칸이다.

 

각 마네킹마다 택시거리가 K 이하인 점을 한번씩 조사한다면 최악의 경우(거의 모든 칸에 마네킹이 들어서있고 K의 값이 큰 경우) 상당히 많은 계산량이 필요해지므로 효율적으로 2)의 경우를 해결할 필요가 있다. 이는 각 마네킹의 위치들을 source로 하는 multisource bfs를 구현하는 것으로 해결이 가능하다.

 

택시거리를 생각할 때 벽 등이 있는지와 상관없이 오로지 좌표의 값만으로 계산한다는 점에 유의하자. 즉, 마네킹으로 인해 접근할 수 있는 칸을 조사할 때 벽 등을 무시하고 bfs를 진행해야 하는 점에 유의하자.

 

아래와 같이 dr 배열과 dc 배열을 이용하면 이와 같은 문제에서의 bfs 구현을 편하게 할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int R, C, K;
int sr, sc;
int arr[2000][2000];
queue<pair<int, int>> que1;
queue<pair<int, int>> que2;

int dr[4] = { 1,-1,0,0 };
int dc[4] = { 0,0,1,-1 };

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> R >> C >> K;
	for (int r = 0; r < R; r++) {
		for (int c = 0; c < C; c++) {
			int& cur = arr[r][c];
			cin >> cur;
			if (cur == 3) que1.push(make_pair(r, c));
			else if (cur == 4) cur = 1, sr = r, sc = c;
		}
	}

	while (K--) {
		int quecnt = que1.size();
		while (quecnt--) {
			int r = que1.front().first, c = que1.front().second; que1.pop();
			for (int i = 0; i < 4; i++) {
				int rr = r + dr[i], cc = c + dc[i];
				if (rr < 0 || rr >= R || cc < 0 || cc >= C) continue;
				if (arr[rr][cc] == 3) continue;
				arr[rr][cc] = 3;
				que1.push(make_pair(rr, cc));
			}
		}
	}

	int ans = 0;
	que2.push(make_pair(sr, sc));
	while (1) {
		ans++;
		int quecnt = que2.size();
		if (quecnt == 0) {
			cout << -1;
			return 0;
		}
		while (quecnt--) {
			int r = que2.front().first, c = que2.front().second; que2.pop();
			for (int i = 0; i < 4; i++) {
				int rr = r + dr[i], cc = c + dc[i];
				if (rr < 0 || rr >= R || cc < 0 || cc >= C) continue;
				if (arr[rr][cc] == 1 || arr[rr][cc] == 3) continue;
				else if (arr[rr][cc] == 2) {
					cout << ans;
					return 0;
				}
				arr[rr][cc] = 3;
				que2.push(make_pair(rr, cc));
			}
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1445 // C++] 일요일 아침의 데이트  (0) 2022.06.29
[BOJ 25309 // C++] K개의 소수  (0) 2022.06.28
[BOJ 25304 // C++] 영수증  (0) 2022.06.27
[BOJ 25308 // C++] 방사형 그래프  (0) 2022.06.27
[BOJ 25306 // C++] 연속 XOR  (0) 2022.06.27

+ Recent posts