2 min read

๋ฐฑ์ค€ 13489๋ฒˆ Vjeลกtica

๋ฌธ์ œ ๋งํฌ

๋…ธ๋“œ ๊ฐœ์ˆ˜๋ฅผ ์ตœ์†Œํ™”์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๊ฐ ๋‹จ์–ด๊ฐ„ prefix๋ฅผ ์ตœ๋Œ€ํ•œ ๊ฒน์น˜๊ฒŒ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. ์ˆœ์„œ๋Š” ์ƒ๊ด€ ์—†์œผ๋ฏ€๋กœ ์•ŒํŒŒ๋ฒณ์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ์„œ, ๊ฒน์น˜๋Š” ๋งŒํผ prefix๋กœ ๋งŒ๋“ค์ž.

๋‹จ์–ด๊ฐ€ ์ตœ๋Œ€ 16๊ฐœ์ด๋ฏ€๋กœ, ๋‹จ์–ด ์‚ฌ์šฉ ์—ฌ๋ถ€๋ฅผ bit๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. dp[mask]dp[mask]๋Š” maskmask์— ํ•ด๋‹นํ•˜๋Š” ๋‹จ์–ด๋“ค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” Trie์˜ ์ตœ์†Œ ๋…ธ๋“œ์˜ ์ˆ˜ ๋ผ๊ณ  ์ •์˜ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ ํ™”์‹์„ ์„ธ์šธ ์ˆ˜ ์žˆ๋‹ค.

dp[mask]=min(dp[mask],dp[sub]+dp[maskโŠ•sub]โˆ’cnt)dp[mask] = min(dp[mask], dp[sub] + dp[mask \oplus sub] - cnt)

subsub๋Š” ํ˜„์žฌ ์„ ํƒํ•œ ๋‹จ์–ด๋“ค์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด๊ณ , cntcnt๋Š” ํ˜„์žฌ ์„ ํƒํ•œ ๋‹จ์–ด๋“ค์˜ ์ตœ๋Œ€ prefix ๊ธธ์ด๋‹ค.

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

int N, cache[1<<16], sz[16], words[16][26];
string s[16];

int get_cnt(int mask) {
    vector<int> acnt(26, 2e9);
    for (int i = 0; i < 16; i++) {
        if ((mask&(1<<i)) == 0) continue;
        for (int j = 0; j < 26; j++) {
            acnt[j] = min(acnt[j], words[i][j]);
        }
    }
    int ret = 0;
    for (int i = 0; i < 26; i++) {
        ret += acnt[i];
    }
    return ret;
}

int solve(int mask) {
    int& ret = cache[mask];
    if (ret != -1) return ret;
    int cnt = get_cnt(mask);
    if (((mask-1)&mask) == 0) return ret = cnt;

    ret = 2e9;
    // iterate through all of its submasks
    for (int sub = (mask-1)&mask; sub > 0; sub = (sub-1)&mask) {
        ret = min(ret, solve(sub) + solve(mask^sub) - cnt);
    }
    return ret;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> s[i];
        for (auto c : s[i]) {
            words[i][c-'a']++;
        }
    }

    memset(cache, -1, sizeof(cache));
    cout << solve((1<<N)-1) + 1 << '\n';

    return 0;
}

์ฃผ์–ด์ง„ maskmask์—์„œ ๋ชจ๋“  submasksubmask๋ฅผ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผ ํ•œ๋‹ค. ๋น„ํŠธ๋งˆ์Šคํฌ์—์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.