엠블란스휘호휘호

BOJ_1987 알파벳 (C++) 본문

프로그래밍/알고리즘

BOJ_1987 알파벳 (C++)

엠블란스휘호휘호 2021. 5. 7. 17:11

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

 

1987번: 알파벳

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

www.acmicpc.net

알파벳 문제입니다. 맵을 입력 받고, 해당 조건에 따라 DFS(깊이 우선 탐색)을 수행하며 원하는 출력을 가져옵니다.

 

핵심함수인 DFS(pair<int, int> _pos, int count)를 설명하면 다음과 같습니다.

 

1. 매개변수는 각각 현재 위치, 지나온 칸의 개수를 의미합니다.

 

2. 깊이 우선 탐색에서 다음으로 갈 수 없는 경우는 다음과 같이 3가지가 존재합니다.

ㄱ. 맵에서 벗어났을 때

>> if (nextY < 0 || nextY >= R || nextX >= C || nextX < 0)

ㄴ. 맵에서 이미 지나온 곳일 때

>> if (check[nextY][nextX] == true)

ㄷ. 맵에 지나온 칸과 같은 알파벳이 적혀 있을 때

>> if(Alphabet[map[nextY][nextX] - 'A'] == true)

 

3. 다음으로 갈 수 있다고 판단되면 다음 위치와, count를 1증가시키며 깊이 탐색을 수행합니다.

>> DFS({ nextY , nextX }, count + 1);

 

4. 해당 위치에서 탐색이 끝나면(더 이상 갈 곳이 없으면) 현재까지 온 칸의 개수를 저장하고,

체크해뒀던 배열의 요소를 다시 풀어줍니다.

>> Alphabet[map[_pos.first][_pos.second] - 'A'] = false;

    check[_pos.first][_pos.second] = false;

 

5. 깊이 탐색을 반복하며 가장 좋은 경우가 answer 변수에 저장됩니다.

// BOJ_1987
// 2020KB, 536ms
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int R, C;
string map[20];
bool check[20][20];
bool Alphabet[26];

int answer = 0;

// 위, 왼쪽, 아래, 오른쪽
pair<int, int> movePos[4] = { {-1, 0},{0, -1},{1, 0},{0, 1} };

void DFS(pair<int, int> _pos, int count)
{
	check[_pos.first][_pos.second] = true;
	Alphabet[map[_pos.first][_pos.second] - 'A'] = true;
	for (int i = 0; i < 4; i++)
	{
		int nextY = _pos.first + movePos[i].first;
		int nextX = _pos.second + movePos[i].second;

		// 맵에서 벗어나면 갈 수 없다.
		if (nextY < 0 || nextY >= R || nextX >= C || nextX < 0)
			continue;

		// 이미 지나온 곳은 갈 수 없다.
		if (check[nextY][nextX] == true)
			continue;

		// 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.
		if(Alphabet[map[nextY][nextX] - 'A'] == true)
			continue;

		// 깊이 탐색
		DFS({ nextY , nextX }, count + 1);
	}
	answer = max(answer, count);

	Alphabet[map[_pos.first][_pos.second] - 'A'] = false;
	check[_pos.first][_pos.second] = false;
}

int main()
{
	cin.tie(nullptr); cout.tie(nullptr);
	ios::sync_with_stdio(false);

	// 첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다.
	cin >> R >> C;

	// 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.
	for (int i = 0; i < R; i++)
		cin >> map[i];
	
	// (0, 0)의 좌표에서 시작해 깊이우선탐색
	DFS({ 0,0 }, 1);

	// 첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.
	cout << answer << '\n';

	return 0;
}

'프로그래밍 > 알고리즘' 카테고리의 다른 글

BOJ_1806 부분합(C++)  (0) 2021.05.08
BOJ_14499 주사위 굴리기 (C++)  (0) 2021.05.06