超蛋疼模拟题,尤其是对我这个不会玩麻将的人来说,根本不知道该怎么判断胡牌,在网上搜到了一个判断胡牌的算法,这个只能判断那种最一般的情况,七小对和十三幺都没有。不过这两个也不怎么难,我把模版贴过来自己写了这两个函数,华丽丽的wa了,改了半天又和网上求这两种和法的函数比较才改好,真心伤不起,还是我代码能力太弱了……
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
map<char,int> convert;
vector<string> ans;
int card[4][10];
char str[5];
int appear[100];
bool Win(int [4][10]);
bool Analyze(int [],bool);
bool Win (int allPai[4][10])
{
int jiangPos;//“将”的位置
int yuShu;//余数
bool jiangExisted=false;
//是否满足3,3,3,3,2模型
for(int i=0; i<4; i++)
{
//yuShu=(int)fmod(allPai[i][0],3);
yuShu=allPai[i][0]%3;
if (yuShu==1)
{
return false;
}
if (yuShu==2)
{
if (jiangExisted)
{
return false;
}
jiangPos=i;
jiangExisted=true;
}
}
for(int i=0; i<4; i++)
{
if (i!=jiangPos)
{
if (!Analyze(allPai[i],i==3))
{
return false;
}
}
}
//该类牌中要包含将,因为要对将进行轮询,效率较低,放在最后
bool success=false;//指示除掉“将”后能否通过
for(int j=1; j<10; j++) //对列进行操作,用j表示
{
if (allPai[jiangPos][j]>=2)
{
//除去这2张将牌
allPai[jiangPos][j]-=2;
allPai[jiangPos][0]-=2;
if(Analyze(allPai[jiangPos],jiangPos==3))
{
success=true;
}
//还原这2张将牌
allPai[jiangPos][j]+=2;
allPai[jiangPos][0]+=2;
if (success) break;
}
}
return success;
}
//分解成“刻”“顺”组合
bool Analyze(int aKindPai[],bool ziPai)
{
if (aKindPai[0]==0)
{
return true;
}
//寻找第一张牌
int j;
for(j=1; j<10; j++)
{
if (aKindPai[j]!=0)
{
break;
}
}
bool result;
if (aKindPai[j]>=3)//作为刻牌
{
//除去这3张刻牌
aKindPai[j]-=3;
aKindPai[0]-=3;
result=Analyze(aKindPai,ziPai);
//还原这3张刻牌
aKindPai[j]+=3;
aKindPai[0]+=3;
return result;
}
//作为顺牌
if ((!ziPai)&&(j<8)
&&(aKindPai[j+1]>0)
&&(aKindPai[j+2]>0))
{
//除去这3张顺牌
aKindPai[j]--;
aKindPai[j+1]--;
aKindPai[j+2]--;
aKindPai[0]-=3;
result=Analyze(aKindPai,ziPai);
//还原这3张顺牌
aKindPai[j]++;
aKindPai[j+1]++;
aKindPai[j+2]++;
aKindPai[0]+=3;
return result;
}
return false;
}
bool isAllpair(int allPai[4][10])
{
int c=0;
for(int i=0;i<4;i++)
{
if(allPai[i][0]%2)
return false;
for(int j=1;j<10;j++)
{
if(allPai[i][j]==2)
c++;
}
}
return c==7;
}
bool otherjudge(int allPai[4][10])
{
int c1=0,c2=0;
for(int i=0;i<3;i++)
{
if(allPai[i][1]>=1)
{
c1++;
if(allPai[i][1]==2)
c2++;
}
if(allPai[i][9]>=1)
{
c1++;
if(allPai[i][9]==2)
c2++;
}
}
for(int i=1;i<=7;i++)
if(allPai[3][i]>=1)
{
c1++;
if(allPai[3][i]==2)
c2++;
}
return c1==13&&c2==1;
}
bool judge()
{
memset(card,0,sizeof(card));
int tot=0;
for(int i=1; i<=37; i++)
{
if(i%10==0)
{
continue;
}
card[i/10][i%10]=appear[i];
card[i/10][0]+=appear[i];
}
if(Win(card))
return true;
else if(isAllpair(card))
return true;
else if(otherjudge(card))
return true;
else return false;
}
int main()
{
//freopen("input.txt","r",stdin);
int t;
scanf("%d",&t);
convert['m']=0;
convert['s']=10;
convert['p']=20;
convert['c']=30;
while(t--)
{
ans.clear();
memset(appear,0,sizeof(appear));
for(int i=0; i<13; i++)
{
scanf("%s",str);
appear[str[0]-'0'+convert[str[1]]]++;
}
for(int i=1; i<=37; i++)
{
if(i%10==0||appear[i]>=4)
continue;
appear[i]++;
if(judge())
{
string temp="";
temp+=(i%10)+'0';
if(i<10)
temp+="m";
else if(i<20)
temp+="s";
else if(i<30)
temp+="p";
else temp+="c";
ans.push_back(temp);
}
appear[i]--;
}
if(ans.size())
{
printf("%d",ans.size());
for(int i=0;i<ans.size();i++)
cout<<" "<<ans[i];
cout<<endl;
}
else cout<<"Nooten"<<endl;
}
}