UVa 11210 - Chinese Mahjong
解题报告:麻将的规则这里就不说了,这题我们可以用暴力的方法,所以我们应该这样枚举,即将34张牌的每一张牌都放到原来的十三张牌里面去,所以这时我们只要判断这十四张牌能不能胡,因为若要胡的话一定要有一个对子,所以这个时候我们应该枚举到底用哪一种牌作为对子,不过还要先判断这种牌的数量是不是大于2,如果大于2说明这种牌可以作为对子。接下来就是判断这十四张牌到底能不能胡的问题。对于这个问题我们可以先把输入的字符串先转化成0到33的对应的数字模式,即0对应1T,1对应2T ...... 33对应BAI,这样我们可以从数字最小的牌开始判断,从0开始,然后分为以下几种情况,第一,这种牌的数量为0,做法是直接跳到下一种牌;第二,这种牌的数量大于等于3,做法是把这种牌作为刻子;第三,这种牌的数量小于3且大于0,这时我们判断从这张牌开始的三张牌以内,这三种牌的数量是否都是大于等于1,如果是,我们就将这三张牌作为顺子,然后把这三种牌的数量分别减少1。如果这三种情况都不满足,直接返回不可以胡。
1 #include<cstdio> 2 #include<cstring> 3 const char feng[50][10]={"","DONG","NAN","XI","BEI","ZHONG","FA","BAI"}; 4 const char hua[50][3]={"T","S","W"}; 5 int mj[40]; 6 int judge(char *p) { 7 if(p[0]>='0'&&p[0]<='9') { 8 if(p[1]=='T') 9 return (p[0]-'0'-1); 10 else if(p[1]=='S') 11 return (8+p[0]-'0'); 12 else return (17+p[0]-'0'); 13 } 14 else { 15 for(int i=1;i<=7;++i) 16 if(!strcmp(feng[i],p)) 17 return (26+i); 18 } 19 } 20 21 bool search(int dep) { 22 int i; 23 for(i=0;i<34;++i) 24 if(mj[i]>=3) { 25 if(dep==3) return true; 26 mj[i]-=3; 27 if(search(dep+1)) return true; 28 mj[i]+=3; 29 } 30 for(i=0;i<=24;++i) 31 if(i%9<=6&&mj[i]>=1&&mj[i+1]>=1&&mj[i+2]>=1) { 32 if(dep==3) return true; 33 mj[i]--; mj[i+1]--;mj[i+2]--; 34 if(search(dep+1)) return true; 35 mj[i]++; mj[i+1]++; mj[i+2]++; 36 } 37 return false; 38 } 39 40 bool check() { 41 for(int i=0;i<34;++i) 42 if(mj[i]>=2) { 43 mj[i]-=2; 44 if(search(0)) return true; 45 mj[i]+=2; 46 } 47 return false; 48 } 49 int main() { 50 char str[10]; 51 int majiang[14],Case=1; 52 while(scanf("%s",str)&&str[0]!='0') { 53 majiang[0]=judge(str); 54 int flag=0; 55 printf("Case %d:",Case++); 56 for(int i = 0; i<12;++i) { 57 scanf("%s",str); 58 majiang[i+1]=judge(str); 59 } 60 for(int i=0;i<34;++i) { 61 memset(mj,0,sizeof(mj)); 62 for(int j=0;j<13;++j) 63 mj[majiang[j]]++; 64 if(mj[i]>=4) 65 continue; 66 mj[i]++; 67 if(check()) { 68 flag=1; 69 if(i>=0&&i<=26) 70 printf(" %d%s",(i%9+1),hua[i/9]); 71 else printf(" %s",feng[i-26]); 72 } 73 } 74 if(!flag) 75 printf(" Not ready"); 76 printf("\n"); 77 } 78 return 0; 79 }