UVa 11210 - Chinese Mahjong

解题报告:麻将的规则这里就不说了,这题我们可以用暴力的方法,所以我们应该这样枚举,即将34张牌的每一张牌都放到原来的十三张牌里面去,所以这时我们只要判断这十四张牌能不能胡,因为若要胡的话一定要有一个对子,所以这个时候我们应该枚举到底用哪一种牌作为对子,不过还要先判断这种牌的数量是不是大于2,如果大于2说明这种牌可以作为对子。接下来就是判断这十四张牌到底能不能胡的问题。对于这个问题我们可以先把输入的字符串先转化成0到33的对应的数字模式,即0对应1T,1对应2T ...... 33对应BAI,这样我们可以从数字最小的牌开始判断,从0开始,然后分为以下几种情况,第一,这种牌的数量为0,做法是直接跳到下一种牌;第二,这种牌的数量大于等于3,做法是把这种牌作为刻子;第三,这种牌的数量小于3且大于0,这时我们判断从这张牌开始的三张牌以内,这三种牌的数量是否都是大于等于1,如果是,我们就将这三张牌作为顺子,然后把这三种牌的数量分别减少1。如果这三种情况都不满足,直接返回不可以胡。

 #include<cstdio>
#include<cstring>
const char feng[][]={"","DONG","NAN","XI","BEI","ZHONG","FA","BAI"};
const char hua[][]={"T","S","W"};
int mj[];
int judge(char *p) {
if(p[]>=''&&p[]<='') {
if(p[]=='T')
return (p[]-''-);
else if(p[]=='S')
return (+p[]-'');
else return (+p[]-'');
}
else {
for(int i=;i<=;++i)
if(!strcmp(feng[i],p))
return (+i);
}
} bool search(int dep) {
int i;
for(i=;i<;++i)
if(mj[i]>=) {
if(dep==) return true;
mj[i]-=;
if(search(dep+)) return true;
mj[i]+=;
}
for(i=;i<=;++i)
if(i%<=&&mj[i]>=&&mj[i+]>=&&mj[i+]>=) {
if(dep==) return true;
mj[i]--; mj[i+]--;mj[i+]--;
if(search(dep+)) return true;
mj[i]++; mj[i+]++; mj[i+]++;
}
return false;
} bool check() {
for(int i=;i<;++i)
if(mj[i]>=) {
mj[i]-=;
if(search()) return true;
mj[i]+=;
}
return false;
}
int main() {
char str[];
int majiang[],Case=;
while(scanf("%s",str)&&str[]!='') {
majiang[]=judge(str);
int flag=;
printf("Case %d:",Case++);
for(int i = ; i<;++i) {
scanf("%s",str);
majiang[i+]=judge(str);
}
for(int i=;i<;++i) {
memset(mj,,sizeof(mj));
for(int j=;j<;++j)
mj[majiang[j]]++;
if(mj[i]>=)
continue;
mj[i]++;
if(check()) {
flag=;
if(i>=&&i<=)
printf(" %d%s",(i%+),hua[i/]);
else printf(" %s",feng[i-]);
}
}
if(!flag)
printf(" Not ready");
printf("\n");
}
return ;
}
上一篇:Razor练习3


下一篇:再谈循环&迭代&回溯&递归&递推这些基本概念