ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 15811 (복면산) c++
    백준 문제 2022. 3. 6. 15:59
    728x90

    문제

     

    15811번: 복면산?!

    복면산이란 수학 퍼즐의 일종으로, 어떤 계산식의 각 숫자들을 특정 문자로 바꾸면 각 문자가 어떤 숫자인지 맞추는 퍼즐이다. 대표적으로 SEND+MORE=MONEY가 있다. SEND + MORE ------ MONEY S=9, E=5, N=6, D=7,

    www.acmicpc.net

    18자리 이하인 영어 대문자 문자열 3개가 주어지는데

    첫번째와 두번째로 주어진 영어 대문자에 서로 겹치지 않는 숫자를 집어넣어 그 둘을 합친게

    세번째로 주어진 문자열과 동일하면 YES를 출력하고 그렇지 않으면 NO를 출력하는 문제입니다.

    예를 들어 문자열이 SUN FUN SWIM 이라고 주어지면

    SUN = 067

    FUN = 867

    라는 숫자를 대입할 수 있습니다. 그 둘을 합치면

    SWIM = 0934 이렇게 값이 일치하는 것을 볼 수 있습니다.

    각 알파벳에는 숫자가 0 ~ 9 까지의 숫자중 1개만 들어갈 수 있고 절대 겹치지 말아야 합니다.

     

    저는 처음에 이렇게 3가지로 구현을 해야한다는 생각이 들었습니다.

    1. 알파벳에 따른 값 저장 어캐?

    2. 알파벳에 값을 0 ~ 9 어캐 분배?

    3. 알파벳에 중복값 체크?

    하지만 구현에 어려움이 생겨 다른분들이 만들었던 코드를 보고 아이디어를 얻어 풀어봤습니다.

    먼저 사용할 배열들과 변수 들입니다.

    str[3] = 입력받을 문자열들입니다.

    alphabet_check[26]=입력 받은 문자열들중에 서로 중복되지않은 알파벳이 몇개 있는 지

    체크해주는 bool 형 배열입니다.

    num_check[10] = 나중에 각 알파벳 마다 숫자를 분배해 줄건데 서로 중복되지 않게 체크해주는 bool 형 배열입니다.

    v[] = alphabet_check에서 true인 값들의 인덱스를 저장할 것입니다. 나중에 알파벳 값을 숫자로 인식하기 위함입니다.

    alphabet[26] = 알파벳에 값을 넣어줄 배열입니다. 예를들어 A는 인덱스가 0이므로 alphabet[0] = ? 가 됩니다.

    물음표에는 분배할 숫자에 따라 여러가지 값이 들어갈 수 있습니다.

    sum[3] = 각 문자열 마다 수가 들어갑니다. 예를들어 첫번째 문자열 SUN = 067 이라면 

    sum[0] = 67 입니다.

    flag = 조건에 만족했을시 flag = true를 설정하고 YES를 출력합니다.


    각각의 문자열을 입력 받고 어떤 알파벳이 들어왔는지 체크해주는 단계 입니다.

    4번째 줄을 보시면 str[i][j] - 'A'  각각의 문자에 대해 인덱스 값을 주는 단계 입니다. 

    EX) A = 0, B = 1, C = 2 ......... X = 23, Y = 24, Z = 25


    alphabet_check에 true로된 위치의 인덱스를 v 벡터에 넣어줍니다.

    7번째 줄을 보면 v.size()가 10이하가 되어야만 recursion함수를 수행할 수 있습니다.

    왜냐하면 각 알파벳 마다 숫자를 분배해야하는데 분배 가능한 숫자는  0~ 9 총 10개의 수 이므로 

    10이 넘어가 버리면 중복되지않은 알파벳이 10개보다 많다는 의미이기 때문입니다.


    이제 알파벳에 숫자를 분배하고 알파벳에 따른 값을 저장할 것입니다.

    recursion 함수는 idx라는 변수를 매개변수로 받습니다. idx는 v 벡터의 인덱스라고 생각하면 됩니다.

     

    먼저 16번째 줄 else문 부터 보면 이제 각 알파벳 마다 서로 다른 수를 분배해 줄것입니다.

    18번째 줄 = num_check[i]가 false란 의미는 현재 i는 아직 분배된 수중에서 안겹친다는 의미입니다.

    따라서 이제 i를 알파벳에 분배를 해줄것입니다.

    20번째 줄을 보면 alphabet[v[idx] = i 란 의미는 alphabet에 i값을 분배해준것입니다.

    예를 들어 alphabet[A] = alphabet[0] = i => A = i 라는 의미입니다.

    이미 벡터 v에는 알파벳의 인덱스값이 들어가 있으므로 v[idx]에 해당하는 알파벳 인덱스에 i값을 넣어주는것과 동일합니다.

    21번째 줄을 보면 재귀함수이므로 idx+1의 값을 매개변수로 넣고 실행해 줍니다.

    22, 23번째 줄을 보면 만약 조건에 맞지 않으면 다시 해야하므로 num_check와 alphabet 배열의 값을 원래 상태로

    되돌려 놓습니다.

     

    이제 3번째 줄을 보면 idx = v.size() 란 의미는 각각의 알파벳에 서로다른 숫자를 분배했다는 의미이므로

    확인을 해봐야 합니다.

    sum에 다가 각 알파벳의 해당하는 숫자를 불러와 값을 저장해줍니다.

    11번째 줄을 보면 이제 확인하는 단계 입니다.


    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <string>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <cmath>
    #include <map>
    #include <set>
    #include <tuple>
    #define MAX 2100000000
    using namespace std;
    using ll = long long;
    using ull = unsigned long long;
    string str[3];
    bool alphabet_check[26];
    bool num_check[10];
    vector<int>v;
    int alphabet[26];
    int sum[3];
    bool flag=false;
    void recursion(int idx);
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
        for (int i = 0; i < 3; i++) {
            cin >> str[i]; 
            for (int j = 0; j < str[i].size(); j++)
                alphabet_check[str[i][j] - 'A'= true;    
        }
        for (int i = 0; i < 26; i++) {
            if (alphabet_check[i]) {
                v.push_back(i);
            }
        }
     
        if (v.size() <= 10)
            recursion(0);
     
        if (flag)cout << "YES";
        else cout << "NO";
        return 0;
    }
    void recursion(int idx) {
        if (flag)return;
        if (idx == v.size()) {
            for (int i = 0; i < 3; i++) {
                sum[i] = 0;
                for (int j = 0; j < str[i].size(); j++) {
                    sum[i] *= 10;
                    sum[i] += alphabet[str[i][j] - 'A'];
                }
            }
            if (sum[0+ sum[1== sum[2]) {
                flag = true;
                return;
            }
        }
        else {
            for (int i = 0; i < 10; i++) {
                if (!num_check[i]) {
                    num_check[i] = true;
                    alphabet[v[idx]] = i;
                    recursion(idx + 1);
                    num_check[i] = false;
                    alphabet[v[idx]] = 0;
                }
            }
        }
    }
    cs

     

Designed by Tistory.