发现可以直接暴力枚举,理由如下:

  • 型是好判的;

  • 型最坏情况下,我们分割它的最坏方案数也就是 ,实际远远达不到这个上界,所以可以接受。

所以,枚举那张牌是什么牌,然后先判断 型,再搜索 型即可。本题有一些细节,需要特别注意。

map<string,int> s2i; map<int,string> i2s;

using cards=vector<int>;

bool dfs(cards c) {
    int rest=0, cnt2=0;
    for (int i=1; i<=39; ++i) {
        rest+=c[i];
        if (c[i]==2) cnt2++;
    }
    if (rest==2) 
        return cnt2;
    for (int i=1; i<=39; ++i) {
        if (c[i]>=3) {
            auto d=c; d[i]-=3;
            if (dfs(d)) return 1;
        }
        if (i>=10 && i%10>=1 && i%10+2<=9) {
            if (c[i]&&c[i+1]&&c[i+2]) {
                auto d=c; d[i]--; d[i+1]--; d[i+2]--;
                if (dfs(d)) return 1;
            }
        }
    }
    return 0;
}

bool ok(cards c) {
    // 2*7
    int cnt=0;
    for (int i=1; i<=39; ++i) {
        if (c[i]%2==0) {
            cnt+=c[i]/2;
        }
    }
    if (cnt==7) return 1;
    // 3+3+3+3+2
    return dfs(c);
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    s2i["bai"]=1;
    s2i["bei"]=2;
    s2i["dong"]=3;
    s2i["fa"]=4;
    s2i["nan"]=5;
    s2i["xi"]=6;
    s2i["zhong"]=7;
    for (int i=1; i<=3; ++i) { // tiao, tong, wan
        for (int j=1; j<=9; ++j) {
            if (i==1) 
                s2i[char(j+'0')+string("tiao")]=i*10+j;
            if (i==2) 
                s2i[char(j+'0')+string("tong")]=i*10+j;
            if (i==3) 
                s2i[char(j+'0')+string("wan")]=i*10+j;
        }
    }
    for (auto [s,i]: s2i) 
        i2s[i]=s;
    cards c(40);
    for (int i=1; i<=13; ++i) {
        string s; cin>>s;
        c[s2i[s]]++;
    }
    map<int,int> mp;
    int cnt=0;
    for (auto [i,s]: i2s) {
        if (c[i]==4) continue;
        cards d=c; d[i]++;
        if (ok(d)) mp[i]=1, cnt++;
    }
    cout<<cnt<<'\n';
    for (int i=1; i<=39; ++i) {
        if (mp[i]) cout<<i2s[i]<<'\n';
    }
}