2019计蒜之道复赛-B-个性化评测系统(打麻将--暴搜)

时限:1000ms              空间限制:262144K

题目链接https://nanti.jisuanke.com/t/39612

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

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

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

这 34 种牌各四张,共 136 张。

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

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

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

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

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

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

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

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

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

输入格式

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

1−9 条用对应数字 + 一个小写 s 表示

1−9 筒用对应数字 + 一个小写 p 表示

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

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

​输入保证有解

输出格式

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

数据组数不超过10 组

样例输入

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

样例输出

2p
5p

。。。题目看得有点晕。其实就是打麻将,和之前UVA11210和HUD4431是一样的。之前有写过题解这里就直接发之前的解释链接了:

题目链接https://blog.csdn.net/qq_43906000/article/details/92598746

实际上我们把上面代码的打的表改一下就可以直接过了。

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;
string sple[]={"1m","2m","3m","4m","5m","6m","7m","8m","9m",
"1s","2s","3s","4s","5s","6s","7s","8s","9s",
"1p","2p","3p","4p","5p","6p","7p","8p","9p",
"1z","2z","3z","4z","5z","6z","7z"};
string s;
int mjid[40],mj[15];
int findid(string s);
int ok(int id);
int check(int stp);
int main()
{
	int num=0;
	while (cin>>s){
		if (cin.eof()) break;
		mj[num++]=findid(s);
		if (num==13){
			num=0;
			int mark=0;
			for (int i=0; i<34; i++){
				memset(mjid,0,sizeof(mjid));
				for (int j=0; j<13; j++)  mjid[mj[j]]++;
				if (mjid[i]>=4) continue;
				mjid[i]++;
				if (ok(i)){
					cout<<sple[i]<<endl;
				}
				mjid[i]--;
			}
		}
	}
	return 0;
}
int findid(string s)
{
	for (int i=0; i<34; i++)
		if (s==sple[i]) return i;
}
int ok(int id)
{
	for (int i=0; i<34; i++){
		if (mjid[i]>=2){
			mjid[i]-=2;
			if (check(0)) return 1;
			mjid[i]+=2;
		}
	}
	return 0;
}
int check(int stp)
{
	for (int i=0; i<34; i++){
		if (mjid[i]>=3){
			if (stp==3) return 1;
			mjid[i]-=3;
			if (check(stp+1)) return 1;
			mjid[i]+=3;
		}
	}
	for (int i=0; i<25; i++){
		if (i%9>6) continue;
		if (mjid[i] && mjid[i+1] && mjid[i+2]){
			if (stp==3) return 1;
			mjid[i]--;mjid[i+1]--;mjid[i+2]--;
			if (check(stp+1)) return 1;
			mjid[i]++;mjid[i+1]++;mjid[i+2]++;
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值