๐Ÿ•๏ธ ICPC Sinchon/Backtracking

[BOJ][C++] ๋ฐฑ์ค€ 9997๋ฒˆ: ํฐํŠธ

์„ ๋‹ฌ 2024. 10. 16. 00:54
๋ฐ˜์‘ํ˜•

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

 

๋ฌธ์ œ

์ƒ๊ทผ์ด๋Š” ์ž์‹ ์ด ๋งŒ๋“  ํฐํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ์žฅ์„ ๋งŒ๋“ค๋ ค๊ณ  ํ•œ๋‹ค. ํฐํŠธ์—๋Š” ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž๋งŒ ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ฌธ์žฅ์€ ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์—๋Š” ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž 26๊ฐœ๊ฐ€ ๋ชจ๋‘ ํฌํ•จ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์‚ฌ์‹ค ๋ฌธ์ œ๋ฅผ ๋งŽ์ด ํ’€์–ด๋ณธ ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ๋ฌธ์ œ๋ฅผ ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ์–ด๋„ ๋ฌด์Šจ ๋ฌธ์ œ์ธ์ง€ ๊ฐ์ด ์žกํ˜€์•ผ ํ•œ๋‹ค.

์ƒ๊ทผ์ด๋Š” ๋‹จ์–ด N๊ฐœ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ์‚ฌ์ „์„ ํ•˜๋‚˜ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์€ ์‚ฌ์ „์— ํฌํ•จ๋œ ๋‹จ์–ด๋งŒ ์ด์šฉํ•ด์„œ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ๋‹จ์–ด๋Š” ํ•œ ๋ฒˆ์”ฉ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๋˜, ๋‹จ์–ด์˜ ์ˆœ์„œ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š๋‹ค. (“uvijek jedem sarmu” ์™€ “jedem sarmu uvijek”๋Š” ๊ฐ™์€ ๋ฌธ์žฅ์ด๋‹ค)

์ƒ๊ทผ์ด๊ฐ€ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

์ž…๋ ฅ

์ฒซ์งธ ์ค„์— ๋‹จ์–ด์˜ ๊ฐœ์ˆ˜ N (1 ≤ N ≤ 25)๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๋‹ค์Œ N๊ฐœ ์ค„์—๋Š” ์‚ฌ์ „์— ํฌํ•จ๋˜์–ด์žˆ๋Š” ๋‹จ์–ด๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๋‹จ์–ด์˜ ๊ธธ์ด๋Š” 100์„ ๋„˜์ง€ ์•Š์œผ๋ฉฐ, ์ค‘๋ณต๋˜๋Š” ๋‹จ์–ด๋Š” ์ฃผ์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.

์ถœ๋ ฅ

์ƒ๊ทผ์ด๊ฐ€ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. 

 

ํ’€์ด

์žฌ๊ท€๋กœ ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋‹ค ๋”ฐ์ ธ๋ณด๋ฉด ๋œ๋‹ค.

 

๊ทผ๋ฐ ๊ทธ ๊ณผ์ •์—์„œ ๋น„ํŠธ๋งˆ์Šคํ‚น์„ ๊ณ๋“ค์—ฌ์„œ... 

(ํ•„์ž๋Š” ๋ณธ ๋ฌธ์ œ๋กœ ๋น„ํŠธ๋ฅผ ์ฒ˜์Œ ๋‹ค๋ค„๋ดค๋‹ค.. ์ž์„ธํ•œ๊ฑด ์•„๋ž˜ ์‹œํ–‰์ฐฉ์˜ค ์ฐธ๊ณ )

// ํ’€์ด : https://whkakrkr.tistory.com

#include <iostream>
#include <vector>

using namespace std;

int n, ans;
vector<int>words; // words[i] : i๋ฒˆ์งธ ๋‹จ์–ด์˜ ๊ฐ ์•ŒํŒŒ๋ฒณ ์‚ฌ์šฉ์—ฌ๋ถ€๋ฅผ ๋น„ํŠธ๋กœ ์ €์žฅ
vector<bool>usedWord; // usedWord[i] : i๋ฒˆ์งธ ๋‹จ์–ด๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋Š”๊ฐ€?

void recur(int k, int usedAlphabet) {
    if(k==n-1) {
        if(usedAlphabet == (1<<26)-1) {
            ans++;
        }
        return;
    }
    
    // ๋‹ค์Œ ๋‹จ์–ด ํฌํ•จ ์•ˆํ•จ
    recur(k+1, usedAlphabet);
    
    // ๋‹ค์Œ ๋‹จ์–ด ํฌํ•จ
    usedWord[k+1] = true;
    recur(k+1, usedAlphabet|words[k+1]);
    usedWord[k+1] = false;
}

int main() {
    cin >> n;
    words.assign(n, 0);
    usedWord.assign(n, false);
    for(int i=0; i<n; i++) {
        string word;
        cin >> word;
        for(char ch : word) {
            words[i] |= (1 << (ch-'a'));
        }
    }
    
    recur(-1, 0);
    
    cout << ans;
    
    return 0;
}

 

 

์‹œํ–‰์ฐฉ์˜ค

์ฒ˜์Œ์—๋Š” ๊ฐ ๋‹จ์–ด๋ฅผ ๊ธธ์ด๊ฐ€ 26์ธ ๋ฐฐ์—ด๋กœ ์ €์žฅํ–ˆ๋‹ค

words[i][j] : i๋ฒˆ์งธ ๋‹จ์–ด๊ฐ€ j๋ฒˆ์งธ ์•ŒํŒŒ๋ฒณ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๊ฐ€ ์—ฌ๋ถ€

 

์—ญ์‹œ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์˜ค๋Š” ์‹œ๊ฐ„์ดˆ๊ณผ.

์žฌ๊ท€๋กœ ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์„ ๋งŒ๋“ค๋•Œ๋งˆ๋‹ค ๋ฐฐ์—ด์„ ๋Œ๋ฉด์„œ ํ•ฉํ•˜๊ณ , 

์žฌ๊ท€๊ฐ€ ๋๋‚  ๋•Œ ๋งˆ๋‹ค ๋ฌธ์žฅ์ด ๋งŒ์กฑํ•˜๋Š”์ง€ (๋ชจ๋“  ์•ŒํŒŒ๋ฒณ์ด true์ธ์ง€) ๋ฐฐ์—ด์„ ๋Œ๊ณ ..

 

์–ด์ฐจํ”ผ 010011101101 ์ด๋Ÿฐ์‹์œผ๋กœ ์ €์žฅํ•˜๊ฒŒ ๋ ํ…๋ฐ

์ด๊ฑธ ๋ฌธ์ž์—ด? ๊ฐ™์ด ํ•˜๋‚˜๋กœ ์ €์žฅํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ 

words[i]๋ฅผ ์ •์ˆ˜๋กœ ์ €์žฅํ–ˆ๋‹ค. ์–ด์ฐจํ”ผ ์ด ์ •์ˆ˜๋ฅผ ์ด์ง„์ˆ˜๋กœ ๋ฐ”๊พธ๋ฉด 011011101 ์ด๋Ÿฐํ˜•ํƒœ๊ฐ€ ๋˜๋‹ˆ๊นŒ.

 

์žฌ๊ท€๋กœ ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์„ ๋งŒ๋“ค๋•Œ๋งˆ๋‹ค ๋น„ํŠธํ•ฉ์—ฐ์‚ฐ | ๋ฅผ ํ•˜๋ฉด๋˜๊ณ 

ํ…Œ์ŠคํŠธ ๋ฌธ์žฅ์ด ๋งž๋Š”์ง€ ๊ฒ€์ฆํ• ๋•Œ๋Š” 2^26-1 (1์ด 26๊ฐœ)์™€ ๊ฐ™์€์ง€๋งŒ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค

 

๋น„ํŠธ ์—ฐ์‚ฐ ์—„์ฒญ ์–ด๋ ค์šด๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ ์ƒ๊ฐ๋ณด๋‹ค ๋ณ„๊ฑฐ ์—†์—ˆ๋˜..!

์ •์ˆ˜ ์—ฐ์‚ฐ์ด๋ž‘ ๋น„์Šท~ํ•˜๋‹ค

๊ดœํžˆ ์ด์ง„์ˆ˜, ๋น„ํŠธ, ์ด๋Ÿฐ๊ฑฐ ๋‹ค๋ฃจ๋‹ˆ๊นŒ ์ „๊ณต์ž ๋œ ๊ฒƒ ๊ฐ™๊ณ .. ๋ฟŒ๋“ฏํ•จ๋„ ๋‘๋ฐฐ์˜€์Œ

// ํ’€์ด : https://whkakrkr.tistory.com

#include <iostream>
#include <vector>

using namespace std;

int n, ans;
vector<vector<bool>>words;
vector<bool>usedWord; // usedWord[i] : i๋ฒˆ์งธ ๋‹จ์–ด๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋Š”๊ฐ€?

bool canTest(vector<bool>&usedAlphabet) {
    for(bool i : usedAlphabet) {
        if(!i) {
            return false;
        }
    }
    return true;
}

void recur(int k, vector<bool>usedAlphabet) {
    if(k==n-1) {
        // ๋กœ๊ทธ
        // for(int i=0; i<n; i++) {
        //     if(usedWord[i]) {
        //         for(int j=0; j<26; j++) {
        //             if(words[i][j]) {
        //                 cout << char(j+'a');
        //             }
        //         }
        //         cout << " ";
        //     }
        // }
        // for(int i=0; i<26; i++) {
        //     cout << usedAlphabet[i];
        // }
        // cout << "\n";
        //
        
        if(canTest(usedAlphabet)) {
            ans++;
        }
        return;
    }
    
    // ๋‹ค์Œ ๋‹จ์–ด ํฌํ•จ ์•ˆํ•จ
    recur(k+1, usedAlphabet);
    
    // ๋‹ค์Œ ๋‹จ์–ด ํฌํ•จ
    usedWord[k+1] = true;
    vector<bool>newUsedAlphabet = usedAlphabet;
    for(int i=0; i<26; i++) {
        if(words[k+1][i]) {
            newUsedAlphabet[i] = true;
        }
    }
    recur(k+1, newUsedAlphabet);
    usedWord[k+1] = false;
}

int main() {
    cin >> n;
    words.assign(n, vector<bool>(26, false));
    usedWord.assign(n, false);
    for(int i=0; i<n; i++) {
        string word;
        cin >> word;
        for(char ch : word) {
            words[i][ch-'a'] = true;
        }
    }
    
    recur(-1, vector<bool>(26,false));
    
    cout << ans;
    
    return 0;
}
๋ฐ˜์‘ํ˜•