1085 - House of Cards

Axel and Birgit like to play a card game in which they build a house of cards, gaining (or losing) credits as they add cards to the house. Since they both have very steady hands, the house of cards never collapses. They use half a deck of standard playing cards. A standard deck has four suits, two are red and two are black. Axel and Birgit use only two suits, one red, one black. Each suit has 13 ranks. We use the notation1R2R...13R1B2B...13B to denote ranks and colors.

The players begin by selecting a subset of the cards, usually all cards of rank up to some maximum value M. After shuffling the modified deck, they take eight cards from the top of the deck and place them consecutively from left to right to form four ``peaks." For instance, if M = 13 and if the first ten cards (from 26) are:

6B 3R 5B 2B 1B 5R 13R 7B 11R 1R ...

then the game starts off with four peaks and three valleys as shown in Figure 7.

\epsfbox{p4451.eps}

Figure 7: Peaks and valleys formed by the top 8 cards in the deck.

The remaining cards are placed face up, in a single row.

Each player is identified with a color, red or black. Birgit is always black and Axel is always red. The color of the first card used for the peaks and valleys determines which player has the first turn. For the example in Figure 7, Birgit has the first turn since the first card is 6B.

Players alternate taking turns. A turn consists of removing the card from the front of the row of cards and then doing one of the following:

  1. Holding the card until the next turn (this is a ``held card").
  2. Covering the valley between two peaks with the drawn card or the held card, forming a ``floor". The remaining card, if any, is held.
  3. Placing two cards over a floor, forming a peak (one of the cards must be a ``held'' card).

Not all options are always available. At most one card may be held at any time, so the first option is possible only if the player is not already holding a card.

Since the cards in the row are face up, both players know beforehand the order in which the cards are drawn.

If the player forms a downward-pointing triangle by adding a floor, or an upward-pointing triangle by adding a peak, then the scores are updated as follows. The sum of the ranks of the three cards in the triangle is added to the score of the player whose color is the same as the majority of cards in the triangle. If no triangle is formed during a play, both scores remain unchanged.

In the example from Figure 7, if Birgit places her card (11R) on the middle valley, she gains 14 points. If she places her card on the left valley, Axel gains 19 points. If she places her card on the right valley, Axel gains 29 points.

If no more cards remain to be drawn at the end of a turn, the game is over. If either player holds a card at this time, the rank of that card is added to (subtracted from) that player's score if the color of the card is the same as (different from) that player's color.

When the game is over, the player with the lower score pays a number of Swedish Kronor (Kronor is the plural of Krona) equal to the difference between the two scores to the other player. In case of a tie there is no pay out.

You must write a program that takes a description of a shuffled deck and one of the players' names and find the highest amount that player can win (or the player's minimum loss), assuming that the other player always makes the best possible moves.

Input 

The input file contains multiple test cases representing different games. Each test case consists of a name (either `Axel' or `Birgit'), followed by a maximum rank M ( 5$ \le$M$ \le$13), followed by the rank and color of the2M cards in the deck in their shuffled order. Every combination of rank (from 1 through M) and color will appear once in this list. The first eight cards form the initial row of peaks from left to right in the order drawn, and the remaining items show the order of the rest of the cards.

The final test case is followed by a line containing the word `End'.

Output 

For each test case, print the test case number (starting with 1), the name of the player for the test case, and the amount that the player wins or loses. If there is a tie, indicate this instead of giving an amount. Follow the sample output format.

Sample Input 

Axel 
5 
1R 2R 3R 4R 5R 5B 4B 3B 2B 1B 
Birgit 
5 
1R 2R 3R 4R 5R 5B 4B 3B 2B 1B 
Birgit 
5 
1R 1B 3R 4R 5R 5B 4B 3B 2R 2B 
End

Sample Output 

Case 1: Axel wins 1 
Case 2: Birgit loses 1 
Case 3: Axel and Birgit tie






#include<stdio.h>
#include<string.h>
#include<string>
#include<stdlib.h>
using namespace std;
struct dat_que
{
	int dir,poi;
}que[9];
struct dat_card
{
	char col;
	int dig;
}card[30];
string order[30];
int inf=100000,n;

int calc_hold_card(int ax_hold,int bi_hold)
{
	int s=0;
	if(ax_hold!=-1)
	{
		if(card[ax_hold].col=='R')
			s+=card[ax_hold].dig;
		else
			s-=card[ax_hold].dig;
	}
	if(bi_hold!=-1)
	{
		if(card[bi_hold].col=='B')
			s-=card[bi_hold].dig;
		else
			s+=card[bi_hold].dig;
	}
	return s;
}

void update(int &rec,int s)
{
	if(s>rec)
		rec=s;
}

int calc_digit(int pha,int p1,int p2,int p3)
{
	int counr,counb,dig;
	counr=counb=dig=0;
	dig=card[p1].dig+card[p2].dig+card[p3].dig;
	if(card[p1].col=='B')
		counb++;
	else
		counr++;
	if(card[p2].col=='B')
		counb++;
	else
		counr++;
	if(card[p3].col=='B')
		counb++;
	else
		counr++;
	if(counr>1)
	{
		if(order[pha]=="Axel")
			return dig;
		else
			return -dig;
	}
	else
	{
		if(order[pha]=="Birgit")
			return dig;
		else
			return -dig;
	}
}

int dfs(int pha,int ax_hold,int bi_hold,int maxn)
{
	if(pha>2*n)
	{
		int s=calc_hold_card(ax_hold,bi_hold);
		if(order[pha]=="Axel")
			return s;
		else
			return -s;
	}
	int rec,i,calc,tmp;
	dat_que temp_que[9];
	rec=-inf;
	memcpy(temp_que,que,sizeof(que));
	tmp=inf;
	if(order[pha]=="Axel"&&ax_hold==-1)
	{
		tmp=dfs(pha+1,pha,bi_hold,rec);
	}
	else if(order[pha]=="Birgit"&&bi_hold==-1)
	{
		tmp=dfs(pha+1,ax_hold,pha,rec);
	}
	update(rec,-tmp);
	if(maxn>=-rec)
		return rec;
	for(i=2;i<=6;i++)
		if(que[i].dir==-1&&que[i+1].dir==1)
		{
			calc=calc_digit(pha,que[i].poi,que[i+1].poi,pha);
			que[i].dir=que[i+1].dir=0;
			que[i].poi=pha;que[i+1].poi=-1;
			tmp=dfs(pha+1,ax_hold,bi_hold,rec-calc);
			update(rec,calc-tmp);
			que[i]=temp_que[i];que[i+1]=temp_que[i+1];
			if(maxn>=-rec)
				return rec;
			if(order[pha]=="Axel"&&ax_hold!=-1)
			{
				calc=calc_digit(pha,que[i].poi,que[i+1].poi,ax_hold);
				que[i].dir=que[i+1].dir=0;
				que[i].poi=ax_hold;que[i+1].poi=-1;
				tmp=dfs(pha+1,pha,bi_hold,rec-calc);
				update(rec,calc-tmp);
			}
			else if(order[pha]=="Birgit"&&bi_hold!=-1)
			{
				calc=calc_digit(pha,que[i].poi,que[i+1].poi,bi_hold);
				que[i].dir=que[i+1].dir=0;
				que[i].poi=bi_hold;que[i+1].poi=-1;
				tmp=dfs(pha+1,ax_hold,pha,rec-calc);
				update(rec,calc-tmp);
			}
			que[i]=temp_que[i];
			que[i+1]=temp_que[i+1];
			if(maxn>=-rec)
				return rec;
		}
	for(i=2;i<=6;i++)
		if(que[i].dir==0&&que[i+1].dir==0&&que[i].poi!=-1&&que[i+1].poi==-1)
		{
			if(order[pha]=="Axel"&&ax_hold!=-1)
			{
				calc=calc_digit(pha,que[i].poi,ax_hold,pha);
				que[i].dir=1;que[i+1].dir=-1;
				que[i].poi=pha;que[i+1].poi=ax_hold;
				tmp=dfs(pha+1,-1,bi_hold,rec-calc);
				tmp=dfs(pha+1,ax_hold,pha,rec);
				update(rec,calc-tmp);
				que[i]=temp_que[i];
				que[i+1]=temp_que[i+1];
				if(maxn>=-rec)
					return rec;
				calc=calc_digit(pha,que[i].poi,ax_hold,pha);
				que[i].dir=1;que[i+1].dir=-1;
				que[i].poi=ax_hold;que[i+1].poi=pha;
				tmp=dfs(pha+1,-1,bi_hold,rec-calc);
				update(rec,calc-tmp);
				que[i]=temp_que[i];
				que[i+1]=temp_que[i+1];
				if(maxn>=-rec)
					return rec;
			}
			else if(order[pha]=="Birgit"&&bi_hold!=-1)
			{
				calc=calc_digit(pha,que[i].poi,bi_hold,pha);
				que[i].dir=1;que[i+1].dir=-1;
				que[i].poi=pha;que[i+1].poi=bi_hold;
				tmp=dfs(pha+1,ax_hold,-1,rec-calc);
				update(rec,calc-tmp);
				que[i]=temp_que[i];
				que[i+1]=temp_que[i+1];
				if(maxn>=-rec)
					return rec;
				calc=calc_digit(pha,que[i].poi,bi_hold,pha);
				que[i].dir=1;que[i+1].dir=-1;
				que[i].poi=bi_hold;que[i+1].poi=pha;
				tmp=dfs(pha+1,ax_hold,-1,rec-calc);
				update(rec,calc-tmp);
				que[i]=temp_que[i];
				que[i+1]=temp_que[i+1];
				if(maxn>=-rec)
					return rec;
			}
		}
	return rec;
}

int main()
{
	int t=0,i,ans,len;
	char name[10];
	while(scanf("%s",&name)&&string(name)!="End")
	{
		t++;
		scanf("%d",&n);
		for(i=1;i<=2*n;i++)
		{
			char z[10];
			scanf("%s",&z);
			len=strlen(z);
			if(len==2)
			{
				card[i].col=z[1];
				card[i].dig=z[0]-'0';
			}
			else
			{
				card[i].col=z[2];
				card[i].dig=(z[0]-'0')*10 + (z[1]-'0');
			}
		}
		for(i=1;i<=8;i++)
		{
			que[i].poi=i;
			if(i%2==1)
				que[i].dir=1;
			else
				que[i].dir=-1;
		}
		if(card[1].col='B')
			order[9]="Birgit";
		else
			order[9]="Axel";
		for(i=10;i<=2*n+1;i++)
		{
			if(order[i-1]=="Birgit")
				order[i]="Axel";
			else
				order[i]="Brigit";
		}
		ans=dfs(9,-1,-1,-inf);
		if(order[9]!=string(name))
			ans*=-1;
		if(ans==0)
		{
			printf("Case %d: Axel and Birgit tie\n",t);
		}
		else if(ans>0)
		{
			printf("Case %d: %s wins %d\n",t,name,ans);
		}
		else
		{
			printf("Case %d: %s loses %d\n",t,name,-ans);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值