문제 번역
더보기
$N*M$크기의 격자 칸에 벼룩을 잡기 위한 트랩을 만들어 두었습니다. 이 트랩에는 약한 방향(상, 하, 좌, 우)이 있어 해당 방향으로 벼룩이 도망갈 수 있습니다. 벼룩의 최대 점프력은 $K$입니다. 벼룩이 $N*M$ 칸을 벗어나면 탈출했다고 표현합니다.
벼룩이 여러 번 점프를 해서 탈출할 수 있는 칸의 개수를 모두 구하십시오.
step 1
더보기
각 격자칸을 정점으로 생각합니다. 벼룩이 칸 $A$에서 칸$B$로 이동할 수 있다면 $B$에서 $A$로 가는 간선을 그려줍니다. 탈출할 수 있는 칸을 전부 구한 다음 그 위치에서 BFS를 돌리면 답을 구할 수 있습니다.
step 2
더보기

각 칸마다 $K$개의 간선이 나올 수 있으므로 $N*M*K$의 시간이 필요합니다. 하지만 이러면 시간초과가 나옵니다.
다음과 같은 상황을 생각해 봅시다.

6번째 칸에서 2번짜 칸으로 가는 간선은 만들어 줄 필요가 없습니다. 6 -> 3 -> 2를 통해 도달할 수 있기 때문이죠. 즉,
- 왼쪽으로 쭉 보면서 간선을 연결해 줍니다.
- L을 만나면 그 칸 까지만 연결하고 더이상 연결하지 않습니다.
이 과정을 L, R, U, D에 대해 다 해주면 됩니다. 그럼 $N*M$에 해결할 수 있습니다.
코드
더보기
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
vector<int> v[4000100];
char mapp[3000][3000];
int ch[4000100];
int n, m;
queue<int> q;
int en(int x, int y) {
return (x - 1) * m + y;
}
int main() {
int d,i,j,k,cnt=0;
scanf("%d%d%d", &n, &m, &d);
for (i = 1;i <= n;i++) {
for (j = 1;j <= m;j++) {
scanf(" %c", &mapp[i][j]);
}
}
for (i = 1;i <= n;i++) {
for (j = 1;j <= m;j++) {
if (mapp[i][j] == 'L') {
for (k = 1;k <= d;k++) {
if (j - k == 0) break;
v[en(i, j - k)].push_back(en(i, j));
if (mapp[i][j - k] == 'L') break;
}
}
}
}
for (i = 1;i <= n;i++) {
for (j = m;j >= 1;j--) {
if (mapp[i][j] == 'R') {
for (k = 1;k <= d;k++) {
if (j + k > m) break;
v[en(i, j + k)].push_back(en(i, j));
if (mapp[i][j + k] == 'R') break;
}
}
}
}
for (i = 1;i <= m;i++) {
for (j = 1;j <= n;j++) {
if (mapp[j][i] == 'U') {
for (k = 1;k <= d;k++) {
if (j - k <= 0) break;
v[en(j - k, i)].push_back(en(j, i));
if (mapp[j - k][i] == 'U') break;
}
}
}
}
for (i = 1;i <= m;i++) {
for (j = n;j >= 1;j--) {
if (mapp[j][i] == 'D') {
for (k = 1;k <= d;k++) {
if (j + k > n) break;
v[en(j + k, i)].push_back(en(j, i));
if (mapp[j + k][i] == 'D') break;
}
}
}
}
for (i = 1;i <= n;i++) {
for (j = 1;j <= m;j++) {
if (mapp[i][j] == 'U' && i <= d) { q.push(en(i, j)); ch[en(i,j)] = 1; }
if (mapp[i][j] == 'D' && i > n-d) { q.push(en(i, j)); ch[en(i, j)] = 1; }
if (mapp[i][j] == 'L' && j <= d) { q.push(en(i, j)); ch[en(i, j)] = 1; }
if (mapp[i][j] == 'R' && j > m-d) { q.push(en(i, j)); ch[en(i, j)] = 1; }
}
}
while (q.size()) {
cnt++;
int i = q.front();
q.pop();
for (j = 0;j < v[i].size();j++) {
if (ch[v[i][j]] == 1) continue;
ch[v[i][j]] = 1;
q.push(v[i][j]);
}
}
printf("%d", cnt);
return 0;
}
'PS - 알고리즘' 카테고리의 다른 글
10523 - 직선 찾기 (0) | 2024.07.11 |
---|---|
1090 - 체커 (0) | 2024.07.11 |
14679 - 영우와 ‘갓4’ (0) | 2024.07.05 |
11401 - 이항 계수 3 (0) | 2024.07.05 |
6612 - 개미의 이동 (0) | 2024.06.27 |