1062

백준 1062번

Link: 1062번: 가르침


문제 설명

29일부터 풀기 시작해서 30일에서 31일 넘어가는 새벽에야 겨우 해결했던 문제.

내 답이 맞는것 같아 계속 고민하다 결국 답을 보고 해결했다.

답을 찾아보고서야 예전에 DFS를 통해 조합을 구하는 방법을 써서 문제를 풀때 어떤식으로 코드를 짰는지 떠오르더라.

정신승리를 좀 하자면, 시간초과가 났긴 했지만 어쨌든 답을 구할 수 있는 방법들을 최대한 생각해보고 여러 방법들을 비교해봤다는 점.

이러는 과정에서 시간초과를 수십번 본 것 같은데, 어떤 부분에서 시간초과가 일어나는지는 짚어냈다.

문제는 그 부분을 고치니 답이 틀렸다는 것.

이렇게 여러번 고민해봐도 도저히 안풀려서 답을 찾아보게 되었다.

답을 보고 나니 뭔가 매우 허무한 느낌이 들었다. 그동안 뭘 짜고 있었나 싶기도 하고.

답을 찾아내기 위해 삽질했던 시간들이 있었기 때문에 정답을 보고서도 이 부분은 나도 구현했는데 왜 틀렸을까 하는 생각이 들게 하였고 이 부분은 이래서 이렇게 짰구나 하는 생각도 들 수 있었던것 같다.

요며칠 단순한 BFS문제를 풀면서 이런식으로 DFS를 통해 조합을 구하고 백트래킹해야 풀리는 문제 푸는 연습을 해야겠다고 생각했는데, 이 문제가 전형적인 그런 문제였다.

시간 지나고 푸는 방법 까먹을때쯤 한번 더 풀어봐야겠다.


삽질했던 코드

#include <iostream>
#include <vector>

using namespace std;

int result = 0;
int N, K;
int candidates[26] = {0, };
int words[50][26] = {0, };

int max(int a, int b){
    return a > b ? a : b;
}

void searchTeach(int count, int index, int toTeach[26], int limit){
    int tempResult = 0;

    int temp[26];
    for(int i=0; i<26; i++){
        temp[i] = toTeach[i];
    }

    if(candidates[index] == 1){
        temp[index] = 1;
    }

    if(count == limit){
        for(int i=0; i<N; i++){
            bool invalid = false;

            for(int j=0; j<26; j++){
                if(toTeach[j] - words[i][j] < 0){
                    invalid = true;
                    break;
                }
            }

            if(!invalid){
                tempResult++;
            }
        }

        result = max(result, tempResult);
        return;
    }

    int next = 0;
    for(int i=index+1; i<26; i++){
        if(candidates[i] == 1){
            next = i;
            break;
        }
    }

    searchTeach(count+1, next, temp, limit);
    searchTeach(count+1, next, toTeach, limit);
}

void toTeach(){
    for(int i=0; i<N; i++){
        for(int j=0; j<26; j++){
            if(candidates[j] != 1){
                candidates[j] = words[i][j];
            }
        }
    }
}

int main(){
    string word;

    cin >> N >> K;

    for(int i=0; i<N; i++){
        cin >> word;

        if(K >= 5){
            string temp = word.substr(4, word.length()-8);
            for(int j=0; j<temp.length(); j++){
                int current = temp[j] - 'a';
                if(current != 0 && current != 2 && current != 8 && current != 13 && current != 19){
                    words[i][current] = 1;
                }
            }
        }
    }

    if(K < 5){
        result = 0;
    }
    else{
        toTeach();

        int input[26] = {0, };

        for(int i=0; i<26; i++){
            if(candidates[i] == 1){
                searchTeach(0, i, input, K-5);
                candidates[i]--;
            }
        }

        if(K == 5){
            searchTeach(0, 0, input, K-5);
        }
    }

    cout << result << '\n';

    return 0;
}

정답 코드

//
// Created by Keith_Lee on 30/01/2019.
//

#include <iostream>
#include <vector>

using namespace std;

int result = 0;
int N, K;

string words[50];
bool visit[26];

int max(int a, int b){
    return a > b ? a : b;
}

void searchTeach(int index, int count){
    if(count == K-5){
        int tempResult = 0;

        for(int i=0; i<N; i++){
            bool invalid = false;

            for(int j=0; j<words[i].length(); j++){
                if(!visit[words[i][j] - 'a']){
                    invalid = true;
                    break;
                }

            }

            if(!invalid){
                tempResult++;
            }
        }

        result = max(result, tempResult);
        return;
    }

    for(int i=index; i<26; i++){
        if(!visit[i]){
            visit[i] = true;
            searchTeach(i, count+1);
            visit[i] = false;
        }
    }

}

int main(){
    cin >> N >> K;

    for(int i=0; i<N; i++){
        cin >> words[i];

        words[i] = words[i].substr(4, words[i].length()-8);
    }

    if(K < 5){
        result = 0;
    }
    else if(K == 26){
        result = N;
    }
    else{
        visit['a' - 'a'] = true;
        visit['n' - 'a'] = true;
        visit['t' - 'a'] = true;
        visit['c' - 'a'] = true;
        visit['i' - 'a'] = true;

        searchTeach(0, 0);
    }

    cout << result << '\n';

    return 0;
}