• UVa 11210


    题目链接

    分析:
    身为一个麻将老手,我都不一定能”听“全牌
    一共只有34种牌,我们可以考虑枚举每一张牌,
    这样问题就可以转化成判断14张牌是否可以“和”

    为此,我们可以枚举将牌,之后每次选三张作为刻子或者顺子
    如图:选将有5种方式
    这里写图片描述

    为了快速的选出将,顺,刻,我们可以用一个34维向量表示每一张牌有多少,
    除了第一次枚举将牌,我们每次只用考虑最小的牌在哪一个顺子或刻子里就好了

    tip

    每种牌只有4张

    //这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const  char *mahjong[]={"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"};
    int mj[15],c[40];
    
    int cl(char *s)
    {
        for (int i=0;i<34;i++)
            if (strcmp(mahjong[i],s)==0) return i;
        return -1;
    }
    
    int solve(int num)                                              //当前已经有的3元组 
    {
        int i;
        for (i=0;i<34;i++)                                          //刻子 
            if (c[i]>=3)
            {
                if (num==4) return 1;
                c[i]-=3;
                if (solve(num+1)) return 1;
                c[i]+=3;
            }
    
        for (i=0;i<27;i++)                                          //顺子 
            if (i%9<=6&&c[i+1]>=1&&c[i+2]>=1&&c[i]>=1)              //没有以8,9开头的顺子
            {
                if (num==4) return 1;
                c[i]--; c[i+1]--; c[i+2]--;
                if (solve(num+1)) return 1;
                c[i]++; c[i+1]++; c[i+2]++;
            } 
    
        return 0;
    }
    
    int check()
    {
        for (int i=0;i<34;i++)        //每种牌都可以作为将
        {
            if (c[i]<2) continue;
            c[i]-=2;
            if (solve(1)) return 1;
            c[i]+=2;
        } 
        return 0;
    }
    
    int main()
    {
        int cas=0;
        char s[10];
        while (scanf("%s",&s)==1)
        {
            if (s[0]=='0') break;
            printf("Case %d:",++cas);
    
            mj[0]=cl(s);
            for (int i=1;i<13;i++)
            {
                scanf("%s",&s);
                mj[i]=cl(s);
            }
    
            bool ff=0;
            for (int i=0;i<34;i++)
            {
                memset(c,0,sizeof(c));
                for (int j=0;j<13;j++) c[mj[j]]++;
    
                if (c[i]==4) continue;
                c[i]++;
                if (check())
                {
                    ff=1;
                    printf(" %s",mahjong[i]);
                }
                c[i]--;
            }
    
            if (!ff) printf(" Not ready");
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    java线程——三种创建线程的方式
    java线程——详解Callable、Future和FutureTask
    商品详情页系统的Servlet3异步化实践
    关于servlet3.0中的异步servlet
    Spring中线程池的应用
    Spring中@Async注解实现“方法”的异步调用
    高性能的关键:Spring MVC的异步模式
    SpringBoot+springmvc异步处理请求
    指定Qt程序运行的style,比如fusion(以前没见过QStyleFactory)
    Linux下获取arm的交叉编译工具链
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7672993.html
Copyright © 2020-2023  润新知