ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[dfs枚举]个性化评测系统

2019-06-22 21:01:10  阅读:260  来源: 互联网

标签:刻子 ke int 张牌 枚举 dfs 91 个性化


“因材施教”的教育方式自古有之,互联网时代,要实现真正意义上的个性化教育,离不开大数据技术的扶持。VIPKID 英语 2020 多万学员每月在课前预习、课中教学、课后复习、作业、答题测评等环节会产生超过 100100 TB 的数据增量,在对庞大数据进行分析之后,个性化评测系统会自动生成针对每个学生的量化学习报告和个性化学习图谱。

正在拿着自己的个性化学习图谱总结分析的 Dino,看到走来的小明手中拿的麻将牌,心生一题,给小明出了一道难题:“你知道怎么输出听牌吗?”看到复杂的规则,小明皱起了眉毛,请你一起来帮小明解决吧!请看题:

在麻将游戏中,有 3434 种牌,分别是 1-91−9 的万,1-91−9 的筒,1-91−9 的条,以及 77 种字牌 “东”,“南”,“西”,“北”,“白”,“发”,“中”。

这 3434 种牌各四张,共 136136 张。

如果你手牌中凑够了 1414 张牌,满足一定的牌型条件,就称作“和牌”。

这个牌型有很多种,但在本题中,只考虑最基本的一种,44 个面子 + 11 个雀头组成的牌型。

面子是刻子和顺子的统称,雀头是对子。

刻子指的是,三张一样的牌。

顺子指的是,三张连续的牌,注意,只有非字牌(也就是万,筒,条)才能连续,例如一二三万,四五六筒,并且不能循环连续,比如九一二条就不算顺子。

对子指的是,两张一样的牌。

现在,zcy 手中有 1313 张牌,并且再得到某一张牌,就可以和牌,而你的目标就是输出能使 zcy 和牌的牌。

注意一种特殊情况,如果你手牌中某张牌有四张,而再得到这张牌也能和牌,这张牌在本题中不需要输出,因为这张牌总共就只有四张,不可能拿到手了。

(如果你知道什么是杠,请假装不能杠,如果你不知道,那就不需要知道了。)

输入格式

1-91−9 万用对应数字 + 一个小写 mm 表示

​1-91−9 条用对应数字 + 一个小写 ss 表示

​1-91−9 筒用对应数字 + 一个小写 pp 表示

​东南西北白发中分别用 1-71−7 的数字 + 一个小写 zz 表示

​输入多组数据,每组共 1313 个数字 + 字母的组合,用空格隔开

​输入保证有解

输出格式

对于每组数据,输出若干行,每行一个听牌,按照万,条,筒,字的顺序输出听牌,同类型按照数从小到大输出

数据组数不超过 1010 组

样例输入

1s 2s 3s 4s 5s 6s 7s 8s 9s 1z 1z 3p 4p

样例输出

2p
5p
  思路:枚举每一个听牌,看能不能胡。 check:先暴力枚举对子,再dfs暴力枚举刻子,再判断剩下的顺子加上之前的刻子是否等于4
#include<bits/stdc++.h>
using namespace std;


map<char,int> mp;
map<int,char> rmp;
char s[15][2];
int cnt[5][10],num[5]={0,9,9,9,7};
int cur[5][10],tmp[5][10];
int ke=0,rec[5][2],vis[5];

bool dfs(int d,int tot,int need){
  if(d==ke+1){
    if(tot==need){
        for(int i=1;i<=4;i++) for(int j=1;j<=num[i];j++) tmp[i][j]=cur[i][j];
        for(int i=1;i<=ke;i++) if(vis[i]) tmp[rec[i][0]][rec[i][1]]-=3;

        int shun=0;
        for(int i=1;i<=3;i++){
            for(int j=1;j<=7;j++){
                while(tmp[i][j]&&tmp[i][j+1]&&tmp[i][j+2]){
                    tmp[i][j]--,tmp[i][j+1]--,tmp[i][j+2]--;
                    shun++;
                }
            }
        }

        return shun+need>=4;
    }
    else return false;
  }

  vis[d]=1;
  if(dfs(d+1,tot+1,need)) return true;
  vis[d]=0;
  if(dfs(d+1,tot,need)) return true;
  return false;
}

bool check(int type,int id){
  for(int i=1;i<=4;i++) for(int j=1;j<=num[i];j++) cur[i][j]=cnt[i][j];
  cur[type][id]++;

  for(int i=1;i<=4;i++){
    for(int j=1;j<=num[i];j++){
        if(cur[i][j]>=2){
            cur[i][j]-=2;

            ke=0;//统计所有能构成刻子的
            for(int k=1;k<=4;k++){
                for(int l=1;l<=num[k];l++){
                    if(cur[k][l]>=3){
                        rec[++ke][0]=k;
                        rec[ke][1]=l;
                    }
                }
            }

            for(int k=0;k<=min(4,ke);k++){
                if(dfs(1,0,k)) return true;//在所有ke个能构成刻子的里面选k个,看是否能胡
            }

            cur[i][j]+=2;
        }
    }
  }

  return false;
}

int main()
{
    mp['m']=1,mp['s']=2,mp['p']=3,mp['z']=4;
    rmp[1]='m',rmp[2]='s',rmp[3]='p',rmp[4]='z';
    while(scanf("%s",s[1])!=EOF){
        memset(cnt,0,sizeof(cnt));
        for(int i=2;i<=13;i++) scanf("%s",s[i]);

        for(int i=1;i<=13;i++){
            cnt[mp[s[i][1]]][s[i][0]-'0']++;
        }

        for(int i=1;i<=4;i++){
            for(int j=1;j<=num[i];j++){
                if(cnt[i][j]<=3&&check(i,j)){
                    //printf("i=%d j=%d\n",i,j);
                    printf("%d%c\n",j,rmp[i]);
                }
            }
        }
    }
    return 0;
}
View Code

 

标签:刻子,ke,int,张牌,枚举,dfs,91,个性化
来源: https://www.cnblogs.com/lllxq/p/11070308.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有