发现可以直接暴力枚举,理由如下:
-
型是好判的;
-
型最坏情况下,我们分割它的最坏方案数也就是
,实际远远达不到这个上界,所以可以接受。
所以,枚举那张牌是什么牌,然后先判断 型,再搜索
型即可。本题有一些细节,需要特别注意。
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';
}
}