http://acm.hdu.edu.cn/showproblem.php?pid=4431
幸亏哥有点麻将基础 提到三种和牌方式
1: 7个不同的对子
2: 传说中的十三幺 m1,m9,s1,s9,p1,p9,c1,c2,c3,c4,c5,c6,c7 然后再多一张 可以是 前面那13张中的任意一张
3: 一个对子 外加 四个 (吃或碰)吃就是三张牌组成的顺子 碰就是三个牌一样
思路 :
枚举添加任意一张牌 但不能使某种牌的个数超过4
然后判定是否是和牌
判定第三种和牌时 先枚举去掉一个对子 然后看是否剩余的牌组成 四个 (吃或碰)
注意:
c1,c2,c3 像 东南西方这类的牌 没有顺子
自己写的时候是因为一个地方数组没有初始化 wa 了很久
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<set> #include<queue> #include<stack> #include<map> #include<string> #include<iomanip> using namespace std; #define LL long long const int INF=0x5fffffff; const double FINF=1e9; const int N=20; int s[N]; int c[N]; int m[N]; int p[N]; vector<int>ans; vector<char>ansc; bool Two() { for(int i=1;i<=9;++i) { if(c[i]!=0&&c[i]!=2) return false; if(m[i]!=0&&m[i]!=2) return false; if(p[i]!=0&&p[i]!=2) return false; if(s[i]!=0&&s[i]!=2) return false; } return true; } bool Spe() { int t2=0; for(int i=1;i<=7;++i) { if(c[i]==2) ++t2; else if(c[i]!=1) return false; } if(m[1]==2) ++t2; else if(m[1]!=1) return false; if(m[9]==2) ++t2; else if(m[9]!=1) return false; if(s[1]==2) ++t2; else if(s[1]!=1) return false; if(s[9]==2) ++t2; else if(s[9]!=1) return false; if(p[1]==2) ++t2; else if(p[1]!=1) return false; if(p[9]==2) ++t2; else if(p[9]!=1) return false; if(t2!=1) return false; return true; } bool Func(int tmp[],int l) { if(tmp[l]==1||tmp[l]==2||tmp[l]==4) { --tmp[l]; if(tmp[l+1]==0) return false; else --tmp[l+1]; if(tmp[l+2]==0) return false; else --tmp[l+2]; } if(tmp[l]==3) tmp[l]=0; return true; } bool Meld() { int s1[N],m1[N],p1[N]; for(int i=1;i<N;++i) { if(c[i]!=0&&c[i]!=3) return false; s1[i]=s[i]; p1[i]=p[i]; m1[i]=m[i]; } int l=1; while(l<=9) { if(!s1[l]&&!m1[l]&&!p1[l]) {++l;continue;} if(!Func(s1,l)) return false; if(!Func(m1,l)) return false; if(!Func(p1,l)) return false; } return true; } bool Normal() { for(int i=1;i<=9;++i) { if(c[i]>=2) { c[i]-=2; if(Meld()) {c[i]+=2;return true;} c[i]+=2; } if(p[i]>=2) { p[i]-=2; if(Meld()) {p[i]+=2;return true;} p[i]+=2; } if(m[i]>=2) { m[i]-=2; if(Meld()) {m[i]+=2;return true;} m[i]+=2; } if(s[i]>=2) { s[i]-=2; if(Meld()) {s[i]+=2;return true;} s[i]+=2; } } return false; } bool Win() { if(Two()) return true; if(Spe()) return true; if(Normal()) return true; return false; } void Fans(int stmp[],char k) { int w=9; if(k=='c') w=7; for(int i=1;i<=w;++i) { if(stmp[i]<4) { ++stmp[i]; if(Win()) {ans.push_back(i);ansc.push_back(k);} --stmp[i]; } } } int main() { //freopen("data.txt","r",stdin); int T; char stmp[5]; scanf("%d",&T); while(T--) { for(int i=0;i<N;++i) s[i]=c[i]=m[i]=p[i]=0; for(int i=1;i<=13;++i) { scanf("%s",stmp); int k=stmp[0]-'0'; if(stmp[1]=='c') ++c[k]; else if(stmp[1]=='p') ++p[k]; else if(stmp[1]=='m') ++m[k]; else if(stmp[1]=='s') ++s[k]; } ans.clear(); ansc.clear(); Fans(m,'m'); Fans(s,'s'); Fans(p,'p'); Fans(c,'c'); if(ans.size()==0) printf("Nooten\n"); else { printf("%d",ans.size()); for(unsigned int i=0;i<ans.size();++i) { printf(" %d%c",ans[i],ansc[i]); } printf("\n"); } } return 0; }