uva11210 Chinese Mahjong

23 篇文章 0 订阅

Mahjong ( ) is a game of Chinese origin usually played by four persons
with tiles resembling dominoes and bearing various designs, which are
drawn and discarded until one player wins with a hand of four
combinations of three tiles each and a pair of matching tiles. A set
of Mahjong tiles will usually differ from place to place. It usually
has at least 136 tiles, most commonly 144, although sets originating
from America or Japan will have more. The 136-tile Mahjong includes:
Dots: named as each tile consists of a number of circles. Each circle
is said to represent copper (tong) coins with a square hole in the
middle. In this problem, they’re represented by 1T , 2T , 3T , 4T , 5T
, 6T , 7T , 8T and 9T . Bams: named as each tile (except the 1 Bamboo)
consists of a number of bamboo sticks. Each stick is said to represent
a string (suo) that holds a hundred coins. In this problem, they’re
represented by 1S , 2S , 3S , 4S , 5S , 6S , 7S , 8S and 9S . Craks:
named as each tile represents ten thousand (wan) coins, or one hundred
strings of one hundred coins. In this problem, they’re represented by
1W , 2W , 3W , 4W , 5W , 6W , 7W , 8W and 9W . Wind tiles: East,
South, West, and North. In this problem, they’re represented by DONG,
NAN, XI, BEI. Dragon tiles: red, green, and white. The term dragon
tile is a western convention introduced by Joseph Park Babcock in his
1920 book introducing Mahjong to America. Originally, these tiles are
said to have something to do with the Chinese Imperial Examination.
The red tile means you pass the examination and thus will be appointed
a government official. The green tile means, consequently you will
become nancially well off. The white tile (a clean board) means since
you are now doing well you should act like a good, incorrupt official.
In this problem, they’re represented by ZHONG, FA, BAI. There are 9
3 + 4 + 3 = 34 kinds, with exactly 4 tiles of each kind, so there are
136 tiles in total. To who may be interested, the 144-tile Mahjong
also includes: Flower tiles: typically optional components to a set of
mahjong tiles, often contain artwork on their tiles. There are exactly
one tile of each kind, so 136+8=144 tiles in total. In this problem,
we don< t consider these tiles. Chinese Mahjong is very complicated.
However, we only need to know very few of the rules in order to solve
this problem. A meld is a certain set of tiles in one’s hand. There
are three kinds of melds you need to know (to who knows Mahjong
already, kong is not considered): Pong: A set of three identical
titles. Example: , . Chow: A set of three suited tiles in sequence.
All three tiles must be of the same suites. Sequences of higher length
are not permissible (unless it forms more than one meld). Obviously,
wind tiles and dragon tiles can never be involved in chows. Example: ,
. Eye: The pair, while not a meld, is the nal component to the
standard hand. It consists of any two identical tiles. A player wins
the round by creating a standard mahjong hand. That means, the hand
consists of an eye and several (possible zero) pongs and chows. Note
that each title can be involved in exactly one eye/pong/chow. When a
hand is one tile short of wining, the hand is said to be a ready hand,
or more guratively, ‘on the pot’. The player holding a ready hand is
said to be waiting for certain tiles. For example is waiting for , and
. To who knows more about Mahjong: don’t consider special winning
hands such as '. Input The input consists of at most 50 test cases.
Each case consists of 13 tiles in a single line. The hand is legal
(e.g. no invalid tiles, exactly 13 tiles). The last case is followed
by a single zero, which should not be processed. Output For each test
case, print the case number and a list of waiting tiles sorted in the
order appeared in the problem description ( 1T ~ 9T , 1S ~ 9S , 1W ~
9W , DONG , NAN , XI , BEI , ZHONG , FA , BAI ). Each waiting tile
should be appeared exactly once. If the hand is not ready, print a
message
Not ready ’ without quotes.

首先枚举要“听”的牌,然后验证这14张牌能否出完。
先枚举“将”,然后搜索,每次找见最小的没有出完的牌,如果能出【碰或者作为串的最小牌】就继续搜,否则直接减枝。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
/*1T~9T:1..9
1S~9S:10..18
1W~9W:19..27
DNXB:28..31
ZFB:32..34*/
int num[40];
bool init()
{
    int i,x;
    char s[10];
    memset(num,0,sizeof(num));
    for (i=1;i<=13;i++)
    {
        scanf("%s",s+1);
        if (s[1]=='0') return 0;
        if (s[1]>='1'&&s[1]<='9')
        {
            x=s[1]-'0';
            if (s[2]=='S') x+=9;
            if (s[2]=='W') x+=18;
        }
        else
        {
            switch (s[1])
            {
                case 'D':x=28;break;
                case 'N':x=29;break;
                case 'X':x=30;break;
                case 'B':x=s[2]=='E'?31:34;break;
                case 'Z':x=32;break;
                case 'F':x=33;break;
            }
        }
        num[x]++;
    }
    return 1;
}
bool dfs(int now)
{
    if (!now) return 1;
    int i;
    bool tem;
    for (i=1;i<=34;i++)
      if (num[i])
      {
        if (num[i]>=3)
        {
            num[i]-=3;
            tem=dfs(now-3);
            num[i]+=3;
            if (tem) return 1;
        }
        if ((i<=7||(i>=10&&i<=16)||(i>=19&&i<=25))
          &&num[i+1]&&num[i+2])
        {
            num[i]--;
            num[i+1]--;
            num[i+2]--;
            tem=dfs(now-3);
            num[i]++;
            num[i+1]++;
            num[i+2]++;
            if (tem) return 1;
        }
        return 0;
      }
}
bool ok()
{
    int i;
    bool tem;
    for (i=1;i<=34;i++)
      if (num[i]>=2)
      {
        num[i]-=2;
        tem=dfs(12);
        num[i]+=2;
        if (tem) return 1;
      }
    return 0;
}
void solve()
{
    int i;
    bool flag=0;
    for (i=1;i<=34;i++)
      if (num[i]<4)
      {
        num[i]++;
        if (ok())
        {
            flag=1;
            printf(" ");
            if (i<=27)
            {
                printf("%d",(i%9)?i%9:9);
                switch ((i-1)/9)
                {
                    case 0:printf("T");break;
                    case 1:printf("S");break;
                    case 2:printf("W");break;
                }
            }
            else
            {
                switch (i)
                {
                    case 28:printf("DONG");break;
                    case 29:printf("NAN");break;
                    case 30:printf("XI");break;
                    case 31:printf("BEI");break;
                    case 32:printf("ZHONG");break;
                    case 33:printf("FA");break;
                    case 34:printf("BAI");break;
                }
            }
        }
        num[i]--;
      }
    if (!flag) printf(" Not ready");
    printf("\n");
}
int main()
{
    int K=0;
    while (init())
    {
        printf("Case %d:",++K);
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值