1. 程式人生 > >hiho 1830(2018 北京網路賽 C)

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;
}