코딩테스트/[BOJ] 문제 풀이

백준 1987 알파벳

_JAEJAE_ 2021. 8. 15. 20:56

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

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net

문제

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다.

말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.

좌측 상단에서 시작해서, 말이 최대한 몇 칸을 지날 수 있는지를 구하는 프로그램을 작성하시오. 말이 지나는 칸은 좌측 상단의 칸도 포함된다.

입력

첫째 줄에 R과 C가 빈칸을 사이에 두고 주어진다. (1 ≤ R,C ≤ 20) 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.

출력

첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.

예제 입력 1 

2 4

CAAB

ADCB

예제 출력 1 

3

예제 입력 2 

3 6

HFDFFB

AJHGDH

DGAGEH

예제 출력 2 

6


[풀이 과정]

1. 문자 하나씩 입력을 받기 위해 %1c를 해줬다.

 

2. 탐색의 시작이 (0, 0)부터이므로 arr[0][0]에 있는 알파벳은 이미 나왔다고 표시한다.

- arr[0][0]-'A'를 하면 A는 0, B는 1, C는 2 등 순서대로 숫자를 나타내게 된다.

 

3. dfs(int x, int y, int cnt)

- 상하좌우 4방향으로 다음 위치를 탐색한다.

- 다음 위치가 범위를 벗어나면 패스한다.

- 다음 위치의 알파벳이 아직 나온적 없으면 나왔다고 체크 후 dfs를 실행한다.(그 위치에서 갈 수 있는 곳 모두 탐색하기 위해)

- 최대 깊이에서의 cnt를 result와 비교 후 업데이트한다.

- dfs가 최대 깊이까지 탐색하고 나오면 해당 위치의 알파벳 체크를 지운다. (다른 경로로 탐색하기 위해) 

 

4. 최종 result값 출력한다.


[소스 코드]

#include <stdio.h>
const int MAX = 25;

char arr[MAX][MAX];
int n, m, alpha[30], result;
int dx[] = { 0, 1, 0, -1 };
int dy[] = { -1, 0, 1, 0 };

void dfs(int x, int y, int cnt) {
	for (int i = 0; i < 4; i++) {
		int nx = x + dx[i];
		int ny = y + dy[i];
        
		if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
        
		if (alpha[arr[nx][ny]-'A'] == 0) {
			alpha[arr[nx][ny] - 'A'] = 1;
			dfs(nx, ny, cnt+1);
			alpha[arr[nx][ny] - 'A'] = 0; # 최대 깊이까지 탐색 끝나면 체크 삭제하기
		}
	}
	if (result < cnt) result = cnt; # 최대 깊이에서의 cnt를 result에 업데이트
}
int main() {
	scanf("%d %d", &n, &m);

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			scanf(" %1c", &arr[i][j]);
		}
	}
	alpha[arr[0][0] - 'A'] = 1;
	dfs(0, 0, 1);

	printf("%d\n", result);
	return 0;
}