ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Baekjoon - 10789] 가상 키보드 입력
    문제 풀이/Baekjoon Online Judge 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

    '문제 풀이 > Baekjoon Online Judge' 카테고리의 다른 글

    [Baekjoon - 2471] 모빌 이진수  (0) 2023.02.14
    [Baekjoon - 22581] IkaNumber  (0) 2023.02.14
    [Baekjoon - 20614] Tree Product  (0) 2023.02.13
    [Baekjoon - 22443] Minus One  (0) 2023.02.13
    [Baekjoon - 3973] Time To Live  (0) 2023.02.13
Designed by Tistory.