[2018.11.03 T4] 7w523

16 篇文章 0 订阅

7w523

题目描述

你玩过7王523吗?

这个扑克牌游戏可以 2~5 个人玩,最开始的时候,每人 5 5 5 张牌,庄家 6 6 6 张牌。庄家首先出牌,然后轮流出牌或不出牌。

第一个出牌的人可以打出任意牌,后面的人必须比前面的牌大才能出牌,且牌型必须要和前面人出牌的牌型一致或大于前面人的牌型。

牌的大小关系是 7>大王>小王>5>2>3>A>K>Q>J>10>9>8>6>4.不区分花色。

牌型有:对子(两张牌点数一样),炸弹(三张牌一样),氢弹(四张牌一样)

牌型的大小关系是:氢弹>炸弹>对子、单牌

另外还有一种特殊的出牌规则,如果有人出单牌,某人手上有一样点数的对子,则有对子的人可以忽略出牌顺序直接“碰”。在“碰”后,后面只有炸弹或氢弹可以出。(比如甲出单牌,后面只要有人有碰,一定是先满足碰)

当某个人打出的牌没人要时,本轮出牌结束,最后一个出牌的人取得本轮胜利,本轮出的牌就是胜利的人的积分, 1 1 1 张牌记 1 1 1 分。再由胜利的人开始在剩余牌中按顺序拿几张牌和手上的牌凑够五张,接下来按顺序另外的人也从剩余牌中按顺序拿够 5 5 5 张。 如果牌库中牌的数量不够某个人拿够 5 5 5张, 则停止拿牌环节。 如果发牌环节结束后某个玩家没有牌, 则整个游戏结束, 同时每个玩家的得分加上其手牌数量。

例如:

甲:2 4 4 6 K

乙:3 8 8 J 10

丙:K K 4 A A

剩余牌:7 7 2

假设出牌顺序是甲、乙、丙;

第一轮:甲先出 6 6 6,则乙可以出 J J J 10 10 10 3 3 3;丙如果不要,则甲可以出 2 2 2。这个时候没有人有牌能够大过 2 2 2,该轮出牌结束,甲获得胜利可以得到 3 3 3 个积分。接下来甲可以从剩余牌中获得 2 2 2 7 7 7,而乙可以获得 2 2 2。丙没有出牌就不能拿。

第二轮:甲出 K K K,这个时候丙可以跳过乙优先进行“碰”,由于其他人没有炸弹,所以丙获得该轮胜利,得到 3 3 3 个积分。

为了简化问题,我们不考虑获胜的策略。也就是说轮到某人出牌,如果他手上的牌有大于前面人出的牌,则他就打出刚好大于前面的牌(有出必出),有“碰”必“碰”。 比如第一个人出 Q Q Q,第二个人牌是 K 333 K333 K333,第三个人牌是 Q Q J QQJ QQJ,则第三个人会先碰出来。因为对于第二个人来说他优先选择出 K K K,所以第三个人先碰。

每一轮第一个出牌的人,优先出手中最小的对子(为了尽可能让别人要不起, 7 除外),没有对子就出最小的单牌,没有单牌出对 7,没有对 7 出最小的炸弹,没有炸弹出氢弹。接下来轮流出牌,出的牌型必须和前面一至或大于前面的牌型,对子、炸弹、氢弹不能拆开出,出牌的原则的刚好大于前面的牌,如果没有大过前面的牌就 P A S S PASS PASS,由后面一个人出牌。如果一个人出的牌其他人都 P A S S PASS PASS,则本轮结束,最后一个出牌的为胜利者。

**注:**大王与小王不在一起算单牌,大王和小王在一起算炸弹(不能拆开),且是仅次于 777 777 777 的最大炸弹。任何氢弹都大于任何炸弹, 包括王炸。若牌库无牌, 且某玩家出牌后刚好打完, 这一回合仍然需要进行完才算游戏结束。

开始的时候,第一个人自动作为庄家先拿前面的 6 6 6 张牌,接下来玩家依次拿 5 5 5 张(若不够则停止拿牌环节)。当没有剩余的牌且发牌环节某个玩家手上没有牌,游戏结束,其他玩家手中的没有打出去的牌自动算为该玩家的积分。

输入输出格式
输入格式

一共 2 2 2 行;

第一行是一个整数 M M M 表示玩家人数,第二行是一个字符串表示初始牌的顺序,其中大王用 G G G 表示,小王用 F F F 表示,10 用 X X X 表示。

输出格式

M M M 行,每行是一个整数,表示第 i i i 个玩家最后获得的积分。

输入输出样例
输入样例#1:
3
25G36Q3885XKK4AA77A
输出样例#1:
13
2
4
样例解释

第一轮:第一个人出 6,然后第二个人出 X,第三个人不要,第一个人出 Q,第二个人出 3,第三个人不要,第一个人出 2,第二个人出 5、三个人不要,第一个人出 G,第二三个人不要,第一轮结束。第一个人获得积分 7,然后获得 77A 三张牌

第二轮:第一个人出 A, 第三个人有碰优先由第三个人碰,第三个人碰后,没有人有炸弹,该轮第三个人胜利。第三个人获得积分 3

第三轮:第三个人出对 K,第一个人出对 7,第一个人取得本轮胜利获得积分 4 第四轮:第一个人出 3,第二个人、第三个人 pass,第一个人取得胜利获得积分 1 第五轮:第一个人出 5,第一个人取得胜利获得积分 1。游戏结束。最后得分:

第一个人:13

第二个人:2

第三个人:4

【数据特点】

对于 100%数据,保证开始每个人至少有一张牌。一副牌中最多只有一张大王和小王,每个点数的牌张数不超过 4,所有字母均为大写,只有 J,Q,K,A,G,X,F,9,8,7,6,5,4,3,2 这些牌。

测试点玩家人数扑克牌总数特殊情况
12 ≤ 11 \le 11 11没有碰、炸弹、氢弹
22 ≤ 54 \le 54 54没有炸弹、氢弹
33 ≤ 16 \le 16 16
43 ≤ 54 \le 54 54没有碰
53 ≤ 54 \le 54 54没有炸弹、氢弹
64 ≤ 21 \le 21 21没有碰
74 ≤ 21 \le 21 21没有王炸
84 ≤ 54 \le 54 54没有碰、炸弹、氢弹
94 ≤ 54 \le 54 54没有炸弹、氢弹
104 ≤ 54 \le 54 54
题解

辣鸡大模拟,不过我大概是全网最短的代码:
1.png

代码
#include<cstdio>
#include<cstring>
#define put(pos,typ,siz) my[pos][siz]=0,cot[pos]-=typ,flag=1,last=(sd){pos,typ,siz}
const int N=15;
struct sd{int pos,typ,siz;}last;
int val[256],my[6][16],cot[6],sta[55],scr[6],top,n,flag;
char ch[55];
int kind[]={0,'4','6','8','9','X','J','Q','K','A','3','2','5','F','G','7'};
void getcard(int pos,int siz)
{
	for(;cot[pos]<siz&&top;++my[pos][sta[top--]],++cot[pos]);
	if(my[pos][13]&&my[pos][14])my[pos][13]=0,my[pos][14]=3;
}
void putcard(int pos)
{
	int typ=last.typ,siz=last.siz;
	if(!typ)
	{
		for(int i=1;i<N;++i)if(my[pos][i]==2){put(pos,2,i);return;}
		for(int i=1;i<=N;++i)if(my[pos][i]==1){put(pos,1,i);return;}
		if(my[pos][N]==2){put(pos,2,N);return;}
		for(int i=1;i<=N;++i)if(my[pos][i]==3){if(i==14)cot[pos]+=1;put(pos,3,i);return;}
		for(int i=1;i<=N;++i)if(my[pos][i]==4){put(pos,4,i);return;}
	}
	for(int i=1;i<=N;++i)if(my[pos][i]==typ&&i>siz){if(i==14&&typ==3)cot[pos]+=1;put(pos,typ,i);return;}
	for(int j=(typ==1?3:typ+1);j<=4;++j)for(int i=1;i<=N;++i)if(my[pos][i]==j){if(i==14&&j==3)cot[pos]+=1;put(pos,j,i);return;}
	flag=0;
}
bool peng(){for(int i=0;i<n;++i)if(last.typ==1&&my[i][last.siz]==2)return put(i,2,last.siz),last=(sd){i,3,-1},1;return 0;}
void game()
{
	for(int i=1;i<=N;++i)val[kind[i]]=i;
	for(int i=strlen(ch+1);i;--i)sta[++top]=val[ch[i]];
	getcard(0,6);for(int i=1;i<n;++i)getcard(i,5);
	for(int pos,cnt;;last.typ=0,scr[last.pos]+=cnt)
	{
		for(int i=0;i<n;++i)getcard((last.pos+i)%n,5);
		if(!top)for(int i=0;i<n;++i)if(!cot[i])return;
		putcard(last.pos),cnt=last.typ;if(last.typ==3&&last.siz==14)cnt-=1;
		if(peng())cnt+=2,pos=last.pos;
		for(pos=(last.pos+1)%n;pos!=last.pos;pos=(pos+1)%n,flag=0)
		{
			putcard(pos);
			if(flag){cnt+=last.typ;if(last.typ==3&&last.siz==14)cnt-=1;}
			if(peng())cnt+=2,pos=last.pos;
		}
	}
}
void in(){scanf("%d%s",&n,ch+1);}
void ac(){game();for(int i=0;i<n;++i)printf("%d\n",scr[i]+cot[i]);}
int main(){in(),ac();}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值