思路:
枚举添加的牌和两张的对子。
每次取编号最小的那张牌配对,全部可以陪玩就说明和了。
注意:
1、每种牌的数量不能超过4。
2、把所有牌型编号后,不能把类似 9 10 11 ( 九桶,一条,二条 ) 这种的看成同花顺。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
#define n 13
#define m 34
map<string,int> mp; //牌对应的序号
string id[m+5];
vector<int> a;
int num[m+5]= {0};
bool still[m+5]= {0};
vector<int> p;
void init() { //初始化编号
for(int i=1; i<=9; i++) {
string x=" ";
x[0]=i+'0';
mp[x+"T"]=i;
id[i]=x+"T";
}
for(int i=10; i<=18; i++) {
string x=" ";
x[0]=i+'0'-9;
mp[x+"S"]=i;
id[i]=x+"S";
}
for(int i=19; i<=27; i++) {
string x=" ";
x[0]=i+'0'-18;
mp[x+"W"]=i;
id[i]=x+"W";
}
mp["DONG"]=28,mp["NAN"]=29,mp["XI"]=30,mp["BEI"]=31;
id[28]="DONG",id[29]="NAN",id[30]="XI",id[31]="BEI";
mp["ZHONG"]=32,mp["FA"]=33,mp["BAI"]=34;
id[32]="ZHONG",id[33]="FA",id[34]="BAI";
}
void print(int x) {
printf("Case %d:",x);
for(int i=0; i<p.size(); i++) {
cout<<' '<<id[p[i]];
}
if(!p.size()) printf(" Not ready");
printf("\n");
}
bool readin() {
memset(num,0,sizeof(num));
a.clear();
for(int i=1; i<=n; i++) {
string x;
if(!(cin>>x)||x[0]=='0') return false;
a.push_back(mp[x]);
num[a[i-1]]++;
}
sort(a.begin(),a.end());
return true;
}
bool judge(int x) { //判断能否以此牌开始组成同花顺
if(1<=x&&x<=7) return true;
if(10<=x&&x<=16) return true;
if(19<=x&&x<=25) return true;
return false;
}
bool dfs(vector<int> b) { //判断是否能和
bool flag=0;
for(int i=0; i<=n; i++) {
if(still[i]) {
flag=true;
still[i]=false;
if(num[b[i]]>=3) {
still[i+1]=still[i+2]=false;
num[b[i]]-=3;
if(dfs(b)) {
still[i]=true;
num[b[i]]+=3;
still[i+1]=still[i+2]=true;
return true;
}
num[b[i]]+=3;
still[i+1]=still[i+2]=true;
}
if(num[b[i]+1]&&num[b[i]+2]&&judge(b[i])) {
int two=-1,three=-1;
for(int j=i; j<=n; j++) {
if(b[j]==b[i]+1&&still[j]&&!(~two)) {
two=j;
still[j]=false;
num[b[j]]--;
}
if(b[j]==b[i]+2&&still[j]&&!(~three)) {
three=j;
still[j]=false;
num[b[j]]--;
}
}
num[b[i]]--;
if(dfs(b)) {
still[i]=true;
still[two]=still[three]=true;
num[b[i]]++,num[b[two]]++,num[b[three]]++;
return true;
}
still[two]=still[three]=true;
num[b[i]]++,num[b[two]]++,num[b[three]]++;
}
still[i]=true;
break;
}
}
if(flag) return false;
return true;
}
void findjiang(int x,vector<int> b) { //枚举两张一样的牌
sort(b.begin(),b.end());
for(int i=1; i<=m; i++) {
if(num[i]>=2) {
for(int j=0; j<=n; j++) {
still[j]=true;
}
num[i]-=2;
int y=0;
for(int j=b.size()-1; j>=0; j--) {
if(b[j]==i) y++,still[j]=false;
if(y>=2) break;
}
if(dfs(b)) {
p.push_back(x);
num[i]+=2;
return;
}
num[i]+=2;
}
}
}
void add() { //枚举添加的牌
p.clear();
for(int i=1; i<=m; i++) {
if(num[i]==4) continue;
num[i]++;
a.push_back(i);
findjiang(i,a);
a.pop_back();
num[i]--;
}
}
int main() {
init();
int T=0;
while(readin()) {
add();
print(++T);
}
return 0;
}