麻雀游戏(mahjong)
1s/512MB
【题目背景】
Yazid 是一名咸鱼,他最近沉迷上了日麻(日本麻将)这一游戏。
【题目描述】
麻将,起源于中国,是由中国汉族人发明的博弈游戏,娱乐用具,一般用骨头、竹 子或塑料制成小长方块,上面刻有花纹或字样,每副136 张。
和一般的麻将游戏一样,日麻中的牌也分为 5 类:
• 万:有数字 1 . . . 9 共 9 种,用m来记录。如:二万记为2m;二万四万五万记为245m。
• 饼:有数字 1 . . . 9 共 9 种,用p来记录。(记录方法与万类似)
• 索:有数字 1 . . . 9 共 9 种,用s来记录。(记录方法与万、饼类似)
• 风牌:有东风E、南风S、西风W、北风N共 4 种。
• 元牌:有白板Wd、发财Gd、红中Rd共 3 种。
其中,万m、饼p、索s统称为数牌;风牌和元牌统称为字牌。每种牌最多有 4 张,也
就是说不可能存在第 5 张1p、Rd或其他任何牌。
每一位玩家每个时刻手上的牌称为手牌。我们可以用上述规则来表示一副手牌。在 本题中,我们保证给出的手牌表示按上述顺序排序。如123m234p456sESWNWdRd就是 合法的,而123p456m(万应在饼之前)、123m57m(所有万应一起描述)、123654s
(同种数牌的描述中数字应有序)、EEERd123456789m(数牌应在字牌之前)这样的都 是不合法的,在输入数据中不会出现这样的情况。
四位玩家围坐成一圈,轮流摸牌。大多数时间里,每位玩家的手牌数是 13 张。一
名玩家摸牌后,如果满足 13 张手牌加上这一张牌组成四面子加一对子的形式,那么你就可以将你的牌推倒,称为胡牌。
其中,对子表示两张相同的牌,而面子分为 3 类:
• 顺子:三张连续的数字牌。如:123p。
• 刻子:三张完全相同的牌。如:WdWdWd;555s等。
• 杠子:一种特殊的刻子,由四张相同的牌组成,本题不考虑。
同样,如果你已经听牌(差一张牌胡牌),那么在任一其他玩家打出你需要的那张牌时,你也可以推倒胡牌,称为荣和。
了解了规则后,Yazid 兴高采烈的开始了游戏。然而,Yazid 发现,很多时候他满足了胡牌的条件,却不能推倒胡牌。经过规则的查阅,Yazid 发现在日麻中胡牌必须要有一种叫做 ‘‘役’’的东西。
通过阅读新手教学,Yazid 了解到,在日麻中,最常见的三个役分别是:立直、断幺、役牌。
• 立直:在门清状态下,如果你已经听牌,那么你可以丢出一根点棒宣告立直。这 时你就凭空多了一个叫做 ‘‘立直’’ 的役。
• 断幺:指胡牌的牌型中没有幺九牌和字牌。幺九牌指的是点数为1 或 9 的数字牌。
• 役牌:由自风、场风或元牌组成的刻子(或杠子)。所谓自风和场风,是在一局游戏中对一位玩家而言固定的两种风牌。
例如,222m333p66677778s这个牌型就有 ‘‘断幺’’ 这个役。(如果宣告过立直,那么又会多出 ‘‘立直’’ 这个役)
再例如,234m234p23444sRdRdRd这个牌型就有 ‘‘役牌中’’ 这个役。(同样地,如果宣告过立直,那么又会多出 ‘‘立直’’ 这个役)
当然啦,作为资深日麻玩家的 ww140142,他还知道上面这个牌型还有 ‘‘三色同顺’’
这个役。但由于 Yazid 太弱了,所以他根本不关注这些厉害的役。
对于役牌,需要特殊说明的是,自风和场风有时需要重复计算。例如在东场中,
Yazid 又恰好坐东家(即对 Yazid 来说自风、场风均为东风),那么东风的刻子(或杠子)就算作 2 组役牌,如222333444p99sEEE这个牌型就有 ‘‘自风东’’、‘‘场风东’’ 两个役。
由于 Yazid 太弱了,所以他根本没法宣告立直(因为他必须鸣牌才能听牌)。现在他摸上来一张牌后,发现自己可以胡牌了。但他不知道自己有哪些役。所以他找到了 你,请你帮他判断他的手牌是否断幺、是否有役牌。
针对熟悉日麻规则选手的提醒:本题不考虑七对子、国士无双等特殊的胡牌形式。
也保证给出的手牌张数均为14,也就是说不存在杠子。
【输入格式】
从文件 mahjong.in 中读入数据。
本题包含多组数据,第一行一个正整数 T 表示数据组数。接下来依次描述每组数据。对于每组数据:
第一行 2 个大写字母,分别依次表示自风和场风,符号与风牌符号一致。其中,场风只可能为东E、南S。
第二行一个字符串描述手牌。保证符合题目描述中的规则,保证手牌数恰好为14, 保证该手牌由四面子加一对子组成。
【输出格式】
输出到文件 mahjong.out 中。
对于每组数据,输出一行 2 个用空格隔开的整数,其中第一个整数表示是否断幺
(断幺为 1,没有断幺为 0),第二个整数表示役牌的组数。
【样例 1 输入】
3
NE
222m333p66677778s
WS
234m234p23444sRdRdRd
EE
222333444p99sEEE
【样例 1 输出】
1 0
0 1
0 2
【样例 2】
见选手目录下的 mahjong/mahjong2.in与 mahjong/mahjong2.ans。
【提示】
断幺和役牌似乎不能共存哦。
【子任务】
对于 30% 的数据,保证 T =1。
对于另外 10% 的数据,保证一定不存在字牌。对于另外 10% 的数据,保证一定不存在 ‘‘役牌’’。对于另外10% 的数据,保证一定存在字牌。
对于另外 10% 的数据,保证一定没有 ‘‘断幺’’。对于另外10% 的数据,保证T ≤ 10。
对于 100% 的数据,保证 T ≤ 104。
题解:这题题目看起来很长,但比较简单。唯一要注意的是:不能将‘WWWd’判为三个‘W’。
Code:
var
t,l,i,k,ans1,ans2:longint;
st:string;
c1,c2:char;
f:array[1..7]of string;
s:array[1..7]of longint;
begin
assign(input,'mahjong.in');reset(input);
assign(output,'mahjong.out');rewrite(output);
readln(t);
f[1]:='Wd';f[2]:='Gd';f[3]:='Rd';
f[4]:='E';f[5]:='S';f[6]:='W';f[7]:='N';
for l:=1 to t do
begin
readln(c1,c2);
readln(st);
ans1:=0;ans2:=0;
fillchar(s,sizeof(s),0);
for i:=1 to 3 do
begin
k:=pos(f[i],st);
while k<>0 do
begin
inc(s[i]);
delete(st,k,2);
k:=pos(f[i],st);
end;
end;
for i:=4 to 7 do
begin
k:=pos(f[i],st);
while k<>0 do
begin
inc(s[i]);
delete(st,k,1);
k:=pos(f[i],st);
end;
end;
if (pos('1',st)=0)and(pos('9',st)=0)and
(s[1]=0)and(s[2]=0)and(s[3]=0)and(s[4]=0)
and(s[5]=0)and(s[6]=0)and(s[7]=0) then inc(ans1);
for i:=1 to 3 do
if s[i]>=3 then inc(ans2);
for i:=4 to 7 do
begin
if (f[i]=c1)and(s[i]>=3) then inc(ans2);
if (f[i]=c2)and(s[i]>=3) then inc(ans2);
end;
writeln(ans1,' ',ans2);
end;
close(input);close(output);
end.