문제
세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다.
말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.
좌측 상단에서 시작해서, 말이 최대한 몇 칸을 지날 수 있는지를 구하는 프로그램을 작성하시오. 말이 지나는 칸은 좌측 상단의 칸도 포함된다.
입력
첫째 줄에 R과 C가 빈칸을 사이에 두고 주어진다. (1 ≤ R,C ≤ 20) 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.
출력
첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.
예제 입력 1
2 4
CAAB
ADCB
예제 출력 1
3
풀이
이 문제에서는 DFS탐색을 진행하면서 지나온 경로의 알파벳들을 확인해야한다.
따라서 알파벳을 확인할 배열 alpha[26]을 사용하였다. 현재 이어서 지나온 알파벳인 경우 1을, 지나오지 않은 않파벳의 경우 0을 저장한다.
재귀를 통해 DFS를 구현하였으므로 더이상 이동 할 수 있는 정점이 없는 경우엔 재귀호출 종료후 이전 정점으로 돌아온다.
그런데 이때 재귀호출을 종료하기 그 위치가 가진 알파벳을 지난지 여부를 다시 지나지 않은 것으로 수정해 주어야한다!
또한 중복되지 않는 알파벳을 따라 움직이기 때문에 다른 경로로 그 위치를 방문할 수도 있다는 생각이 들어 방문여부를 확인하는 visited배열의 그 위치도 다시 0으로 만들어주었다. (혹시라도 시간초과가 날까봐 걱정했으나 문제없이 실행되었다.)
#include <iostream>
#include <cstdio>
#include <vector>
char map[20][20];
int visited[20][20];
int alpha[26];
int X[4] = {1, -1, 0, 0};
int Y[4] = {0, 0, 1, -1};
void dfs(int x, int y, int r, int c);
int cnt, max;
int main(void){
int r, c;
scanf("%d %d", &r, &c);
for(int i=0; i<r; i++){
scanf("%s", map[i]);
}
dfs(0, 0, r, c);
printf("%d\n", max);
}
void dfs(int x, int y, int r, int c){
int there_x;
int there_y;
int ap;
visited[x][y] = 1;
ap = map[x][y] - 'A';
alpha[ap] = 1;
cnt++;
if(max < cnt)
max = cnt;
for(int i=0; i<4; i++){
there_x = x + X[i];
there_y = y + Y[i];
if(there_x < 0 || there_x >= r || there_y < 0 || there_y >= c)
continue;
ap = map[there_x][there_y] - 'A';
if(visited[there_x][there_y] == 1 || alpha[ap] == 1)
continue;
dfs(there_x, there_y, r, c);
}
ap = map[x][y] - 'A';
alpha[ap] = 0;
visited[x][y] = 0;
cnt--;
}
'알고리즘 > PS - 백준' 카테고리의 다른 글
[백준 2583 - C++] 영역 구하기 : DFS (0) | 2021.02.09 |
---|---|
[백준 11403 - C++] 경로찾기 (0) | 2021.02.08 |
[백준 2468 - C++] 안전 영역 : DFS (0) | 2021.02.08 |
[백준 1260 - C++] DFS와 BFS : DFS & BFS (0) | 2021.02.08 |
[백준 2493 - C++] 탑 : 스택 (stack) (0) | 2021.02.07 |