https://www.acmicpc.net/problem/1987
1987번: 알파벳
세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으
www.acmicpc.net
dfs로 풀면 쉬운 문제인데 bfs로는 또 잘 안 풀리는 문제이다.
보드의 각 칸을 노드, 상하좌우로 인접한 노드의 관계를 에지로 보면 주어진 문제는 중복된 가중치를 발견하지 않고 최대한 많은 노드를 탐색하는 문제임을 알 수 있다.
#include <cstdio>
#define MAX_N 20
// used[i]: 알파벳 i + 'A'를 이미 지났다면 true, 아니라면 false
bool used[26];
//알파벳 보드를 저장할 공간
char arr[MAX_N][MAX_N];
// r, c: 알파벳 보드의 크기, max: 현재까지 지난 최대 칸 수
int r, c, max = 0;
// 좌표 (x, y)를 cnt번만에 도착했을 때 다음으로 갈 곳을 찾는다
void step(int y, int x, int cnt) {
// 만일 현재 발판의 알파벳이 이미 지난 알파벳인 경우 return
if (used[arr[y][x] - 'A']) return;
// 현재 알파벳을 지났음을 표시한 뒤
used[arr[y][x] - 'A'] = true;
// max를 갱신한다
if (max < ++cnt) max = cnt;
// 현재 발판의 상하좌우가 존재한다면 해당 칸에 대해서 같은 과정을 실행한다
if (y - 1 >= 0) step(y - 1, x, cnt);
if (y + 1 < r) step(y + 1, x, cnt);
if (x - 1 >= 0) step(y, x - 1, cnt);
if (x + 1 < c) step(y, x + 1, cnt);
//현재 칸의 알파벳을 지나지 않았던 것으로 계산한다
used[arr[y][x] - 'A'] = false;
}
int main() {
//보드의 크기와 각 칸을 입력받는다
scanf("%d %d%*c", &r, &c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) scanf("%c", &arr[i][j]);
scanf("%*c");
}
// DFS를 실행한 다음 최대 이동 횟수를 출력한다
step(0, 0, 0);
printf("%d", max);
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
1992번: 쿼드트리 (0) | 2021.12.14 |
---|---|
1991번: 트리 순회 (0) | 2021.12.14 |
1978번: 소수 찾기 (0) | 2021.12.13 |
1977번: 완전제곱수 (0) | 2021.12.13 |
1967번: 트리의 지름 (0) | 2021.12.13 |