UVa 11210 Chinee Mahjong 中国麻将

题意就不细说了,就是给你一手麻将牌,按照题目的规定,判断可以和哪些牌。若不能和牌输出Not ready






暴力,非常的暴力。。。。一共34张牌,给定了13张牌,然后直接枚举每张牌作为第14张牌加进去看是否能和牌,能和牌直接输出即可。判断和牌可以用递归实现:这里注意判断和牌时的处理技巧,先按照题目给的牌的种类进行排序,然后依次枚举其中可以做将牌的种类,去掉两张将牌,然后将剩下的12张牌,从最小的牌开始消除,优先消除刻子(原因很简单,打个比方比如有123123123,可以写成3个123,当然也可以写成3个1,3个2,3个3,所以优先消除刻子避免重复枚举)。如果最后牌能全部消除完则说明能和牌。





#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;

const string type[34] =
{
    "1T", "2T", "3T", "4T", "5T", "6T", "7T", "8T", "9T",
    "1S", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S",
    "1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W",
    "DONG", "NAN", "XI", "BEI", "ZHONG", "FA", "BAI"
};
map <string, int> id; //每张牌的序号映射,用来比较牌的顺序

char s[10];
vector <string> mahjong, finish; //分别保存原始13张麻将和加入一张牌后排序的14张麻将
vector <string> temp; //临时保存finish
int cnt[34]; //每张牌的个数

bool cmp(string s1, string s2)
{
    return id[s1] < id[s2];
}

bool DFS()
{
    if(temp.size() == 0)
        return true;
    if(temp[0] == temp[1] && temp[0] == temp[2]) //刻子
    {
        temp.erase(temp.begin(), temp.begin() + 3);
        return DFS();
    }
    if(temp[0][0] < '1' || temp[0][0] > '7') //非数字牌和8、9数字牌开头无法组成顺子
        return false;
    int pos1 = -1, pos2 = -1; //与temp[0]组成顺子的两张牌的位置
    for(int i = 0; i < temp.size(); i++)
    {
        if(id[temp[i]] == id[temp[0]] + 1)
            pos1 = i;
        if(id[temp[i]] == id[temp[0]] + 2)
            pos2 = i;
    }
    if(pos1 == -1 || pos2 == -1)
        return false;
    temp.erase(temp.begin() + pos2);
    temp.erase(temp.begin() + pos1);
    temp.erase(temp.begin());
    return DFS();
}

bool judge(int x)
{
    finish.clear();
    finish.push_back(type[x]);
    for(int i = 0; i < mahjong.size(); i++)
        finish.push_back(mahjong[i]);
    sort(finish.begin(), finish.end(), cmp);
    int i = 0;
    while(i < finish.size())
    {
        bool flag = false;
        while(i + 1 < finish.size() && finish[i] == finish[i + 1])
        {
            flag = true;
            i++;
        }
        if(flag)
        {
            temp.clear();
            for(int j = 0; j < finish.size(); j++)
            {
                if(j < i - 1 || j > i)
                    temp.push_back(finish[j]); //去掉一对将牌
            }
            if(DFS())
                return true;
        }
        i++;
    }
    return false;
}

void input()
{
    mahjong.clear();
    mahjong.push_back(s);
    memset(cnt, 0, sizeof(cnt));
    cnt[id[s]]++;
    for(int i = 1; i < 13; i++)
    {
        scanf("%s", s);
        mahjong.push_back(s);
        cnt[id[s]]++;
    }
}

void solve()
{
    bool ans = false;
    for(int i = 0; i < 34; i++)
    {
        if(cnt[i] < 4 && judge(i))
        {
            if(ans)
                printf(" ");
            else
                ans = true;
            printf("%s", type[i].begin());
        }
    }
    if(!ans)
        printf("Not ready");
    printf("\n");
}

int main()
{
    id.clear();
    for(int i = 0; i < 34; i++)
        id[type[i]] = i;
    int Case = 0;
    while(scanf("%s", s) && s[0] != '0')
    {
        input();
        printf("Case %d: ", ++Case);
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值