ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ 20047, C++] 동전 옮기기
    알고리즘/BOJ 2021. 9. 10. 10:45
    반응형

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

     

    20047번: 동전 옮기기

    입력은 표준입력을 사용한다. 첫 번째 줄에 나열된 동전 개수를 나타낸 양의 정수 n (3 ≤ n ≤ 10,000)이 주어진다. 다음 두 줄에 n 개의 동전이 나열된 상태인 S 와 T 가 각각 주어지며, 이 때 S와 T

    www.acmicpc.net

     

    알고리즘학회 soo7652, kimtaehyun98님의 풀이를 들었음

    투포인터로 접근 했었는데, N의 값이 작으면 걍 DP부터 생각해보는게 나은 것 같음. 참고로 투포인터를 사용하면 S[idx1] == T[idx2]일 때, idx1 += 1, idx2 += 1이 아닌 선택한 동전을 S에 넣고 idx2+=1을 하는 방법을 구현하기가 매우 어렵게 됩니다.

     

     

    풀이

    간단한 문제 풀이를 생각해보면 왼쪽에서부터 S와 T를 하나씩 비교해보다가 서로 다른 문자인 경우에는 선택한 두 동전중 하나를 사용하여 S에 넣어주면 되고, 서로 같은 문자인 경우에는 다음 인덱스로 넘어가거나 선택한 두 동전중 하나를 사용하여 S에 넣어주는 방법을 생각해볼 수 있습니다.

     

    이때 선택한 두 동전을 넣는 경우의 수는 동전의 순서가 정해져있으므로 (선택한 동전을 S에 넣지 않을 때), (첫 번째 동전만 S에 넣었을 때), (두 번째 동전까지 S에 넣었을 때) 세 가지 방법만 존재합니다.

    거기다가 n의 값이 최대 10,000이기 때문에 모든 경우의 수를 확인하는 배열을 생각해보면 dp[10,000][3]이므로 메모이제이션도 사용해볼만 합니다.

     

    함수의 이름은 go(int x, int idx, int y)로 뒀는데, x는 S의 인덱스 번호, y는 선택한 동전을 넣은 개수, y는 T의 인덱스 번호입니다.

    만약 S[x] == T[y]라면 go(x+1, idx, y+1)을 하여 다음 인덱스로 넘어가게 해줄 수 있고, coin[idx] == T[y]라면 선택한 동전을 S에 넣어줘서 go(x, idx+1, y+1)을 해줄 수도 있습니다.

    마지막에는 y == n이 되고, idx == 2가 된다면 두 동전을 모두 S에 넣어서 T로 변환했다는 것이니 1을 반환하고, 아니라면 0을 반환하게 하여 go(0, 0, 0) = 1이면 YES를 출력하고, go(0, 0, 0) = 0이라면 NO를 출력해주면 됩니다.

     

    코드

    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
    52
    53
    54
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <vector>
    using namespace std;
    using ll = long long;
     
    const int N = 10001;
    int n, a, b, dp[N][3];
    string s, t;
    vector<char> S, T;
    char arr[3];
     
    int go(int x, int idx, int y) {
        if (y == n) {
            if (idx == 2return 1;
            else return 0;
        }
     
        int& ret = dp[y][idx];
        if (ret != -1return ret;
     
        ret = 0;
        if (x < n - 2 && S[x] == T[y]) ret = max(ret, go(x + 1, idx, y + 1));
        if (idx < 2 && arr[idx] == T[y]) ret = max(ret, go(x, idx + 1, y + 1));
     
        return ret;
    }
     
    int main()
    {
        ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
        memset(dp, -1sizeof(dp));
     
        cin >> n;
        cin >> s;
        cin >> t;
        cin >> a >> b;
     
        arr[0= s.at(a);
        arr[1= s.at(b);
     
        for (int i = 0; i < n; i++) {
            if (i == a || i == b) continue;
            S.push_back(s.at(i));
        }
        for (int i = 0; i < n; i++) {
            T.push_back(t.at(i));
        }
     
     
        if (go(000)) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    cs
    반응형

    댓글

Designed by Tistory.