hiho 1830(2018 北京网络赛 C) - 模拟

题目链接:点击这里

 

解题思路:

play1 : 按相应等级出一张,不能的话只能说谎且出字典序最小的一张.

挑战1: 陈述者出的rank为X的牌数为p,play1手里rank为X的牌为q,q+p>4,挑战陈述者.

挑战2:下一个陈述者是play1且play1下次陈述必须说谎,挑战陈述者

 

paly2:出完手上相应等级的牌,不能的话只能说谎且出字典序最小的一张

挑战1:下一个陈述者是play2且play2下次陈述必须说谎,挑战陈述者

 

play3:出完手上相应等级的牌,不能的话只能说谎且出完手上数量最小的那个rank,如果有多个选择,选字典序小的那个.

挑战1::play3手上有4张当前陈述者的rank.挑战陈述者

 

play4:如果手上有相应rank的牌3张或者4张,出完该rank牌,不能的话只能说谎且出完相应rank的牌加上一张字典序最小的一张(如果有的话)

挑战1::当陈述者清空了手上的牌时,挑战陈述者

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int mx = 1e3+10;
const int a[] = {9,1,2,3,4,5,6,7,8,0,10,12,11};//字典序 
int n,m,rem[20];
int cnt[6][20];
char str[10];
int Get(){
	if(str[0] == 'A')return 0;
	if(str[0] == 'J')return 10;
	if(str[0] == 'Q')return 11;
	if(str[0] == 'K')return 12;
	if(str[0] == '1')return 9;
	return (int)(str[0]-'0'-1);
}
void input(int x){
	if(x==0) putchar('A');
	else if(x>=1&&x<=8) putchar(x+'0'+1);
	else if(x==9) printf("10");
	else if(x==10) putchar('J');
	else if(x==11) putchar('Q');
	else putchar('K');
	putchar(' ');
}
bool cut(int H)//减去一张字典序最小的牌 
{
	for(int i=0;i<13;i++)
	if(cnt[H][a[i]]){
		cnt[H][a[i]]--;
		rem[a[i]]++;			
		return 1; 
	}	
	return 0;
}
pair<int,int> down(int H,int beg,int v1)
{
	if(cnt[H][beg]){
		if(v1){
			cnt[H][beg]--,rem[beg]++;
			return make_pair(1,1);
		}else{
			rem[beg] += cnt[H][beg];
			int v = cnt[H][beg];
			cnt[H][beg] = 0;
			return make_pair(1,v);
		}
	}else{
		cut(H);
		return make_pair(0,1);
	}
}
pair<int,int> Put(int H,int beg)//相应的出牌规则 
{
	if(H<2) return down(H,beg,H^1);
	else if(H==2){
		if(cnt[H][beg]){
			rem[beg] += cnt[H][beg];
			int v = cnt[H][beg];
			cnt[H][beg] = 0;
			return make_pair(1,v);
		}else{
			int mi = 100,p;
			for(int i=0;i<13;i++)
			if(cnt[H][a[i]]&&mi>cnt[H][a[i]]) mi = cnt[H][a[i]],p = a[i];
			
			rem[p] += cnt[H][p];
			int v = cnt[H][p];
			return make_pair(cnt[H][p] = 0,v);
		}
	}else{
		rem[beg] += cnt[H][beg];
		int v = cnt[H][beg];
		cnt[H][beg] = 0;	
		if(v<3&&cut(H)) return make_pair(0,v+1);
		return make_pair(1,v);
	}
}
bool empty(int H)
{
	for(int i=0;i<13;i++)
	if(cnt[H][i]) return 0;
	return 1;
}
bool check(int x,int H,int beg,int v)//是否挑战 
{
	if(x==0){
		if(v+cnt[x][beg]>4) return 1;
		if((H+1)%4==x&&cnt[x][(beg+1)%13]==0) return 1;
	}else if(x==1){
		if((H+1)%4==x&&cnt[x][(beg+1)%13]==0) return 1;
	}else if(x==2){
		if(cnt[x][beg]==4) return 1;
	}else{
		if(empty(H)) return 1;
	}
	return 0;
}
int solve()
{
	int H = 0,beg = 0;
	while(1){
		pair<int,int> pa = Put(H,beg);
		for(int i=0;i<4;i++)
		if(i!=H&&check(i,H,beg,pa.se)){
			int g = pa.fi? i:H;//收回桌上的牌 
			for(int j=0;j<13;j++) cnt[g][j] += rem[j],rem[j] = 0; 
			break;
		}
		if(empty(H)) return H;
		H = (H+1)%4,beg = (beg+1)%13;
	}
}
int main()
{
	while(~scanf("%s",str))
	{
		memset(cnt,0,sizeof(cnt));
		memset(rem,0,sizeof(rem));
		cnt[0][Get()]++;
		for(int i=0;i<12;i++){
			scanf("%s",str);
			cnt[0][Get()]++;
		}
		for(int i=1;i<=3;i++){
			for(int j=1;j<=13;j++){
				scanf("%s",str);
				cnt[i][Get()]++;
			}
		}
		int ans = solve();
		for(int i=0;i<4;i++){
			if(ans==i) puts("WINNER");
			else{
				for(int j=0;j<13;j++)
				while(cnt[i][j]--) input(j);
				puts("");
			}
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值