문제 풀이/Baekjoon Online Judge

[Baekjoon - 10789] 가상 키보드 입력

hibye1217 2023. 2. 13. 23:31

난이도: Platinum IV

 

태그

더보기
  • Breadth First Search (In 2D grid)

 

풀이

1. 그래프를 정의해보자.

더보기

정점은 튜플 \( (r, c, i) \) = \( i \)개의 글자를 쓴 뒤 \( (r, c) \) 위치로 오는 경우 로 잡고,

간선은 각 \( (r, c) \)에서 상/하/좌/우/선택 중 하나의 키를 누를 때 가게 되는 위치에 연결하면 됩니다.

선택의 경우, 실제로 맞는 글자일 때만 연결해야겠죠.

 

문제의 답은 \( (1, 1, 0) \)에서 출발해서 \( (*, *, |S|) \)로 가는 최단 경로가 됩니다.

 

2. 시간복잡도 / 공간복잡도에 대한 걱정

더보기

시간복잡도와 공간복잡도 모두 \( O(NM|S|) \)가 됩니다.

AC를 받아도, TLE/MLE를 받아도 딱히 할 말은 없는 복잡도죠.

 

3. 구현 디테일

더보기

\( (r, c, i) \)에서 상/하/좌/우 로 이동할 때, 매번 계산하는 건 시간 낭비입니다.

// 게다가 이건 복잡도에 \( O(N) \)을 곱해버리는, 무서운 행동입니다.

대신, \( (r, c) \)에서 갈 수 있는 4개의 칸을 미리 전처리 한 뒤 그걸 사용해야겠죠.

 

4. 코드

더보기
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
char mp[52][52];
pi2 mov[52][52][4];
 
int dis[52][52][10020];
 
void Main(){
    int n, m; cin >> n >> m;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){ cin >> mp[i][j]; }
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            for (int d = 0; d < 4; d++){
                int y = i, x = j;
                while (1 <= y && y <= n && 1 <= x && x <= m){
                    if (mp[y][x] != mp[i][j]){ mov[i][j][d] = {y, x}; break; }
                    y += dy[d]; x += dx[d];
                }
            }
        }
    }
    string s; cin >> s; s += "*"int sl = s.size();
    memset(dis, -1sizeof(dis)); dis[1][1][0= 0;
    queue<pi3> q; q.push({ {11}, 0 });
    while (!q.empty()){
        pi3 p = q.front(); q.pop();
        int y = p.fr.fr, x = p.fr.sc, si = p.sc;
        //cout << "BFS " << y << ' ' << x << ' ' << si << " = " << dis[y][x][si] << endl;
        if (si == sl){ cout << dis[y][x][si]; return; }
        for (int d = 0; d < 4; d++){
            int yy = mov[y][x][d].fr, xx = mov[y][x][d].sc;
            if (yy == 0){ continue; }
            if (dis[yy][xx][si] != -1){ continue; }
            q.push({ {yy, xx}, si }); dis[yy][xx][si] = dis[y][x][si]+1;
        }
        if (s[si] == mp[y][x]){
            if (dis[y][x][si+1!= -1){ continue; }
            q.push({ {y, x}, si+1 }); dis[y][x][si+1= dis[y][x][si]+1;
        }
    }
}
cs