HDU 4431 Mahjong(神奇的麻将) 模拟

胡牌的情况

1、有1对相同的牌(对子),和4组meld(对不起我实在不知道怎么翻译了)。meld就是3张相同的牌或者3张连续的牌(顺子)。注意3张连续的c牌不能看做meld。

2、有7对不同的对子。

3、有1s,9s,1m,9m,1p,9p,和1c至7c这13种牌,并且其中有1种牌有2张。

做法是枚举1张牌加入牌组(第14张牌),然后判断当前牌组能不能胡。

对于第一种胡牌情况,先选出1对对子,在判断剩下的是不是4组meld.

对于第二、三种情况就直接判断了。

需要注意的是,每种牌最多只有4张,需要在每次枚举时判一下。(我卡在这好久)

以及这道题每行输出末尾如果有空格好像会PE。(啊。。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 40
using namespace std;
int q[maxn],ans;
bool jud0(int c[])
{
    int i,cnt[maxn];
    for (i=1;i<=37;i++) cnt[i]=c[i];
    for (i=1;i<30;i++)
    {
        if (i%10==0) continue;
        if (cnt[i]>=3) cnt[i]-=3;
        if (cnt[i]>0 && i%10<8)
        {
            cnt[i+1]-=cnt[i];
            cnt[i+2]-=cnt[i];
            cnt[i]=0;
        }
        if (cnt[i]!=0) return 0;
    }
    for (i=31;i<=37;i++)
    {
        if (cnt[i]>=3) cnt[i]-=3;
        if (cnt[i]!=0) return 0;
    }
    return 1;
}
bool jud1(int c[])
{
    int i,tot=0,cnt[maxn];
    for (i=1;i<=37;i++) cnt[i]=c[i];
    for (i=1;i<=37;i++)
        if (cnt[i]>=2) tot++;
    if (tot==7) return 1;
    return 0;
}
bool jud2(int c[])
{
    int i,flag=1,tot=0,cnt[maxn];
    for (i=1;i<=37;i++) cnt[i]=c[i];
    for (i=0;i<3;i++)
        if (!cnt[i*10+1] || !cnt[i*10+9]) flag=0;
        else tot+=cnt[i*10+1]+cnt[i*10+9];
    for (i=1;i<=7;i++)
        if (!cnt[30+i]) flag=0;
        else tot+=cnt[30+i];
    if (flag && tot==14) return 1;
    return 0;
}
int main()
{
    int i,j,t,tmp,c[maxn],flag;
    char s[10];
    scanf("%d",&t);
    while (t--)
    {
        memset(c,0,sizeof(c));
        ans=0;flag=1;
        for (i=1;i<14;i++)
        {
            scanf("%s",s);
            if (s[1]==‘m‘) tmp=s[0]-‘0‘;
            if (s[1]==‘s‘) tmp=s[0]-‘0‘+10;
            if (s[1]==‘p‘) tmp=s[0]-‘0‘+20;
            if (s[1]==‘c‘) tmp=s[0]-‘0‘+30;
            c[tmp]++;
            if (c[tmp]>4) flag=0;
        }
        if (!flag)
        {
            printf("Nooten\n");
            continue;
        }
        for (i=1;i<=37;i++)
        {
            if (i%10==0 || c[i]>3) continue;
            c[i]++;flag=0;
            for (j=1;j<=37;j++)
                if (c[j]>=2 && j%10!=0 && !flag)
                {
                    c[j]-=2;
                    if (!flag && jud0(c))
                    {
                        q[++ans]=i;flag=1;
                    }
                    c[j]+=2;
                }
            if (!flag)
            {
                if (jud1(c)|| jud2(c)) q[++ans]=i;
            }
            c[i]--;
        }
        if (ans==0) printf("Nooten\n");
        else
        {
            printf("%d",ans);
            for (i=1;i<=ans;i++)
            {
                if (q[i]>30) printf(" %dc",q[i]-30);
                else if (q[i]>20) printf(" %dp",q[i]-20);
                else if (q[i]>10) printf(" %ds",q[i]-10);
                else printf(" %dm",q[i]);
            }
            printf("\n");
        }
    }
    return 0;
} 

(写得我累死了)

原文地址:https://www.cnblogs.com/lsykk/p/12185950.html

时间: 2024-11-18 00:28:17

HDU 4431 Mahjong(神奇的麻将) 模拟的相关文章

HDU 4431 Mahjong (麻将、神坑模拟题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4431 题面: Mahjong Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4219    Accepted Submission(s): 842 Problem Description Japanese Mahjong is a fou

HDU - 4431 Mahjong (模拟+搜索+哈希+中途相遇)

题目链接 基本思路:最理想的方法是预处理处所有胡牌的状态的哈希值,然后对于每组输入,枚举每种新加入的牌,然后用哈希检验是否满足胡牌的条件.然而不幸的是,由于胡牌的状态数过多(4个眼+一对将),预处理的复杂度太高($O(34^5)$),因此需要想办法优化一下. 我们可以预处理出所有“加上一对将之后可以胡牌”的状态,这样预处理的复杂度就成了$O(34^4)$,在可接受的范围内了.在检验的时候,只需要枚举去掉哪一对将,就可以$O(1)$检验是否能胡牌了(有种中途相遇的感觉),另外两种特殊情况单独判断即

HDU - 4431 Mahjong

中华文化真是博大精深 这两天的Dark模拟题做的我要吐了 题目大意:给你13张麻将,求再加上哪张可以胡 胡的要求有三个 1.一个对子 +  4组 3个相同的牌或者顺子.  只有m.s.p是可以构成顺子的.东西南北这样的牌没有顺子. 2.7个不同的对子. 3.1m,9m,1p,9p,1s,9s,1c,2c,3c,4c,5c,6c,7c.  这13种牌每种都有,而且仅有这13种牌.肯定是有一种2张.其他的1张. 具体思路:枚举加那张牌,然后按题意模拟,判断是否胡了即可 我貌似wa了一页的样子,原因是

HDU 4431 Mahjong (DFS,暴力枚举,剪枝)

题意:给定 13 张麻将牌,问你是不是“听”牌,如果是输出“听”哪张. 析:这个题,很明显的暴力,就是在原来的基础上再放上一张牌,看看是不是能胡,想法很简单,也比较好实现,结果就是TLE,一直TLE,这不科学啊... 好不容易写出来的,竟然TLE...心痛.就是先确定一个将牌,然后再对刻子和顺子进行分析,其实是要剪枝的,就是在如果有1张或者两张牌,而你又不能构成刻子的时候,就要返回false,因为这就已经没解了. 这一个剪枝,就AC了. 代码如下: #pragma comment(linker,

hdu 5640 King&#39;s Cake(模拟)

Problem Description It is the king's birthday before the military parade . The ministers prepared a rectangle cake of size n×m(1≤n,m≤10000) . The king plans to cut the cake himself. But he has a strange habit of cutting cakes. Each time, he will cut

hdu 4930 Fighting the Landlords (模拟)

Fighting the Landlords Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 160    Accepted Submission(s): 52 Problem Description Fighting the Landlords is a card game which has been a heat for ye

hdu 5379 Mahjong tree(树形dp)

题目链接:hdu 5379 Mahjong tree 树形dp,每个节点最多有2个子节点为一棵节点数大于1的子树的根节点,而且要么后代的节点值都大于,要么都小于本身(所以tson不为0是,要乘2).对于K个单一节点的子节点,种类数即为全排K!.当一个节点没有兄弟节点时,以这个节点为根结点的子树,根可以选择最大或者最小. #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #inclu

hdu 4891 The Great Pan (模拟)

为什么要开__int64 巨巨在哪~ # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int main () { __int64 count; int i,len,cot,cot1,j,flag,n; char a[1001][1030]; while(~scanf("%d",&n)) { getchar(); flag=0

HDU 4930 Fighting the Landlords(模拟)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 解题报告:斗地主,加了一个四张可以带两张不一样的牌,也可以带一对,判断打出一手牌之后,如果对手没有能够大过你的牌就输出Yes,或者如果你把手上的牌一次性打完也输出Yes,否则输出No,代码有280多行,表示光是敲代码就花了一个多小时,手速还是太慢. 1.首先判断手上的牌能不能一次打完 如果一次性打不完: 2.首先判断对方有没有一对王,有就输出No 3.判断对手有没有四张的牌,如果有,再判断自己