허비의 기술블로그

[BOJ] 알파벳(1987) - C++ 본문

BOJ

[BOJ] 알파벳(1987) - C++

허비1411 2022. 9. 29. 17:14

R X C의 2차원 보드의 각 위치에 영문 대문자가 들어있다. (0, 0)의 좌표에서 상하좌우 중 한 방향으로 이동하려고 하는데, 가려고 하는 좌표의 값이 이미 지나온 경로에 있는 값이라면 갈 수 없다. 이때 이동할 수 있는 최대 거리를 구하는 문제이다.

 

1987번: 알파벳

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

www.acmicpc.net


풀이 과정

(0, 0)의 좌표에서 이동하면서 현재까지 지나온 값을 저장해야 한다. 보드의 값이 대문자 알파벳(A ~ Z) 26개로 한정돼 있으므로 26개 길이의 배열을 선언해 각 알파벳의 사용 여부 (True / False)를 저장한다. 4방향 중에 한 방향으로 탐색을 진행한 후에는 다른 방향으로도 진행이 가능하다면 탐색을 해야 하므로 그래프 탐색 기법인 '깊이 우선 탐색(DFS)'를 활용한다.

갈 수 있는 최대 길이를 정답으로 출력해야 하므로 각 탐색마다 정답으로 출력할 값을 현재 값과, 현재 재귀 깊이(탐색한 횟수)와 비교하며 더 큰 값으로 업데이트해줘야 한다.

 


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#define MAXN 20
using namespace std;
 
int ans = 0;
int dx[4= { -1100 };
int dy[4= { 00-11 };
int R, C;
 
void DFS(int depth, int x, int y, bool bucket[], char matrix[MAXN][MAXN], bool visited[MAXN][MAXN]) {
 
    bucket[matrix[x][y] - 'A'= true;
    ans = ans > depth + 1 ? ans : depth + 1;
    visited[x][y] = true;
 
    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
 
        if (0 <= nx && nx < R and 0 <= ny && ny < C && visited[nx][ny] == false) {
            if (bucket[matrix[nx][ny] - 'A'== false)
                DFS(depth + 1, nx, ny, bucket, matrix, visited);
 
        }
    }
    bucket[matrix[x][y] - 'A'= false;
    visited[x][y] = false;
}
 
int main(void) {
 
    bool bucket[26= { false };
    char matrix[MAXN][MAXN];
    bool visited[MAXN][MAXN] = { false };
    cin >> R >> C;
    for (int i = 0; i < R; i++)
        for (int j = 0; j < C; j++)
            cin >> matrix[i][j];
    
 
    DFS(000, bucket, matrix, visited);
    cout << ans << endl;
}
cs

 

주석 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#define MAXN 20
using namespace std;
 
int ans = 0;
int dx[4= { -1100 }; // 상하좌우 방향배열
int dy[4= { 00-11 };
int R, C; //행의 수, 열의 수
 
void DFS(int depth, int x, int y, bool bucket[], char matrix[MAXN][MAXN], bool visited[MAXN][MAXN]) { //재귀 깊이, x좌표, y좌표, 보드, 방문여부
 
    bucket[matrix[x][y] - 'A'= true// 현재 좌표 알파벳 방문 체크
    ans = ans > depth + 1 ? ans : depth + 1// 정답(최대값) 갱신
    visited[x][y] = true// 방문 체크
 
    for (int i = 0; i < 4; i++) { // 상하좌우 4방향
        int nx = x + dx[i]; // 다음 x좌표
        int ny = y + dy[i]; // 다음 y좌표
 
        if (0 <= nx && nx < R and 0 <= ny && ny < C && visited[nx][ny] == false) { // 다음 좌표가 보드 범위 내에 있고 방문하지 않았었다면
            if (bucket[matrix[nx][ny] - 'A'== false// 지나온 경로에 다음 좌표 값이 없었다면
                DFS(depth + 1, nx, ny, bucket, matrix, visited); // 다음 위치로 이동
 
        }
    }
    bucket[matrix[x][y] - 'A'= false// 혀재 좌표 알파벳 방문 체크 해제
    visited[x][y] = false// 방문 여부 초기화
}
 
int main(void) {
 
    bool bucket[26= { false }; // 알파벳이 나왔는 지 여부를 저장할 배열 (알파벳 대문자 26개)
    char matrix[MAXN][MAXN]; // 보드
    bool visited[MAXN][MAXN] = { false }; // 방문 여부 체크
    cin >> R >> C; // 행, 열 입력
    for (int i = 0; i < R; i++)
        for (int j = 0; j < C; j++)
            cin >> matrix[i][j]; // 보드 입력
    
 
    DFS(000, bucket, matrix, visited); // DFS로 그래프 탐색
    cout << ans << endl// 저장된 최대 길이 출력
}
cs

채점 결과

처음에 방문 여부를 unordered_set을 써서 집합으로 관리를 했는데, 시간 초과가 났다. 이유가 생각나지 않아서 질문을 올려봐야겠다.

+) 질문 답변 결과

unordered_set도 hashSet 구조이기 때문에 추가와 삽입이 O(1) 시간이어서 시간 초과가 나지 않아야 한다고 생각했다. 하지만 정확히 1의 시간이 걸리는 것이 아니라 해쉬 함숫값 관리에 필요한 상수값이 클 수도 있어서 시간 초과가 난다는 답변을 받았다. 즉 N에 비례해 시간이 증가하는 것은 아니지만 삽입, 삭제에 상수 시간으로 시간이 오래 걸리므로 시간 초과가 났다.

시간 초과 코드 (주석을 모두 지우고, bucket 배열 대신 uset을 쓰면 시간 초과)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#define MAXN 20
//#include <unordered_set>
using namespace std;
 
int ans = 0;
int dx[4= { -1100 };
int dy[4= { 00-11 };
int R, C;
 
//void DFS(int depth, int x, int y, unordered_set<char> & uset, char matrix[MAXN][MAXN], bool visited[MAXN][MAXN]) {
void DFS(int depth, int x, int y, bool bucket[], char matrix[MAXN][MAXN], bool visited[MAXN][MAXN]) {
 
    //uset.insert(matrix[x][y]);
    bucket[matrix[x][y] - 'A'= true;
    ans = ans > depth + 1 ? ans : depth + 1;
    visited[x][y] = true;
 
    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];
 
        if (0 <= nx && nx < R and 0 <= ny && ny < C && visited[nx][ny] == false) {
            //if (uset.find(matrix[nx][ny]) == uset.end())
            if (bucket[matrix[nx][ny] - 'A'== false)
                //DFS(depth + 1, nx, ny, uset, matrix, visited);
                DFS(depth + 1, nx, ny, bucket, matrix, visited);
 
        }
    }
    //uset.erase(matrix[x][y]);
    bucket[matrix[x][y] - 'A'= false;
    visited[x][y] = false;
}
 
int main(void) {
 
    //unordered_set<char> uset;
    bool bucket[26= { false };
    char matrix[MAXN][MAXN];
    bool visited[MAXN][MAXN] = { false };
    cin >> R >> C;
    for (int i = 0; i < R; i++)
        for (int j = 0; j < C; j++)
            cin >> matrix[i][j];
    
 
    //DFS(0, 0, 0, uset, matrix, visited);
    DFS(000, bucket, matrix, visited);
    cout << ans << endl;
}
cs

'BOJ' 카테고리의 다른 글

[BOJ] 키 순서(2458) - C++  (1) 2022.09.30
[BOJ] 소수의 연속합(1644) - PYTHON  (0) 2022.08.15
[BOJ] 오르막 수(11057) - PYTHON  (0) 2022.06.29
[BOJ] 치킨 배달(15686) - PYTHON  (0) 2022.06.27
[BOJ] 부분수열의 합(1182) - PYTHON  (0) 2022.06.26
Comments