UVa 246 10-20-30

 10-20-30 

A simple solitaire card game called 10-20-30 uses a standard deck of 52 playing cards in which suit is irrelevant. The value of a face card (king, queen, jack) is 10. The value of an ace is one. The value of each of the other cards is the face value of the card (2, 3, 4, etc.). Cards are dealt from the top of the deck. You begin by dealing out seven cards, left to right forming seven piles. After playing a card on the rightmost pile, the next pile upon which you play a card is the leftmost pile.

For each card placed on a pile, check that pile to see if one of the following three card combinations totals 10, 20, or 30.

 
		 1. 		 the first two and last one,

2. the first one and the last two, or

3. the last three cards.

If so, pick up the three cards and place them on the bottom of the deck. For this problem, always check the pile in the order just described. Collect the cards in the order they appear on the pile and put them at the bottom of the deck. Picking up three cards may expose three more cards that can be picked up. If so, pick them up. Continue until no more sets of three can be picked up from the pile.

For example, suppose a pile contains 5 9 7 3 where the 5 is at the first card of the pile, and then a 6 is played. The first two cards plus the last card (5 + 9 + 6) sum to 20. The new contents of the pile after picking up those three cards becomes 7 3. Also, the bottommost card in the deck is now the 6, the card above it is the 9, and the one above the 9 is the 5.

If a queen were played instead of the six, 5 + 9 + 10 = 24, and 5 + 3 + 10 = 18, but 7 + 3 + 10 = 20, so the last three cards would be picked up, leaving the pile as 5 9.

If a pile contains only three cards when the three sum to 10, 20, or 30, then the pile "disappears" when the cards are picked up. That is, subsequent play skips over the position that the now-empty pile occupied. You win if all the piles disappear. You lose if you are unable to deal a card. It is also possible to have a draw if neither of the previous two conditions ever occurs.

Write a program that will play games of 10-20-30 given initial card decks as input.

Input

Each input set consists of a sequence of 52 integers separated by spaces and/or ends of line. The integers represent card values of the initial deck for that game. The first integer is the top card of the deck. Input is terminated by a single zero (0) following the last deck.

Output

For each input set, print whether the result of the game is a win, loss, or a draw, and print the number of times a card is dealt before the game results can be determined. (A draw occurs as soon as the state of the game is repeated.) Use the format shown in the ``Sample Output" section.

Sample Input

2 6 5 10 10 4 10 10 10 4 5 10 4 5 10 9 7 6 1 7 6 9 5 3 10 10 4 10 9 2 1
10 1 10 10 10 3 10 9 8 10 8 7 1 2 8 6 7 3 3 8 2
4 3 2 10 8 10 6 8 9 5 8 10 5 3 5 4 6 9 9 1 7 6 3 5 10 10 8 10 9 10 10 7
2 6 10 10 4 10 1 3 10 1 1 10 2 2 10 4 10 7 7 10
10 5 4 3 5 7 10 8 2 3 9 10 8 4 5 1 7 6 7 2 6 9 10 2 3 10 3 4 4 9 10 1 1
10   5 10 10 1 8 10 7 8 10 6 10 10 10 9 6 2 10 10
0

Sample Output

Win : 66
Loss: 82
Draw: 73
 
 
#include <cstdio>
#include <deque>
#include <vector>
#include <set>
using namespace std;
// pile[0]记录手上的牌,pile[1-7]记录牌堆
vector<deque<int> > pile;

set<vector<deque<int> > > state_set;


int deal_count = 0;

bool check(int num);

int main()
{
	int x;
	while(scanf("%d", &x) && x != 0)
	{
		deal_count = 0;
		pile = vector<deque<int> >();
		for(int i = 0; i <= 7; i++)
		{
			pile.push_back(deque<int>());
		}
		state_set = set<vector<deque<int> > >();

		pile[0].push_back(x);
		// 初始化手上的牌
		for(int i = 1; i <= 51; i++)
		{
			scanf("%d", &x);	
			pile[0].push_back(x);
		}

		// 先发每堆两张
		for(int r = 1; r <= 2; r++)
		{
			for(int j = 1; j <= 7; j++)
			{
				int now_card = pile[0].front();
                        	pile[0].pop_front();
                        	pile[j].push_back(now_card);
                        	deal_count++;				
				state_set.insert(pile);	
			}
		}

		// 开始发牌
		// 如果stop_flag为0代表输,为1代表赢,为2代表平
		int stop_flag = 0;	
		int deal_pile_num = 1;	
		while(pile[0].size() > 0)
		{
			int now_card = pile[0].front();
			pile[0].pop_front();
			pile[deal_pile_num].push_back(now_card);
			deal_count++;

			// 检查牌堆,并变换
			while(check(deal_pile_num))
				;

			// 查看当前状态是否重复
			if(state_set.find(pile) != state_set.end())
			{
				stop_flag = 2;
				printf("Draw: %d\n", deal_count);
				break;
			}
			// 如果不重复,记录当前状态
			state_set.insert(pile);
			
			int i;
			for(i = 1; i <= 7; i++)		
				if(pile[i].size() > 0)
					break;
			// 如果牌堆全部消失,就赢
			if(i == 8)
			{
				stop_flag = 1;
				printf("Win : %d\n", deal_count);
				break;
			}
			// 找到下一个放的牌堆
			int k = deal_pile_num % 7;
			while(pile[k+1].size() == 0)
				k = (k+1) % 7;	
			deal_pile_num = k+1;								
		}
		// 如果手上的牌发完,就输
		if(stop_flag == 0)
		{
			printf("Loss: %d\n", deal_count);
		}
			
	}
	return 0;	
}

// 检查pile[num]牌堆,并变换
bool check(int num)
{
	if(pile[num].size() < 3)
		return false;
	int x1,x2,x3;
	// 查看前两张和最后一张		
	x1 = pile[num].front();
	pile[num].pop_front();
	x2 = pile[num].front();
	x3 = pile[num].back();
	if( (x1+x2+x3) == 10 || (x1+x2+x3) == 20 || (x1+x2+x3) == 30)
	{
		pile[num].pop_front();
		pile[num].pop_back();
		pile[0].push_back(x1);
		pile[0].push_back(x2);
		pile[0].push_back(x3);
		return true;		
	}
	// 查看前一张和最后两张
	else
	{
		pile[num].pop_back();
		x2 = pile[num].back();
		if( (x1+x2+x3) == 10 || (x1+x2+x3) == 20 || (x1+x2+x3) == 30)
        	{
			pile[num].pop_back();
			pile[0].push_back(x1);
                	pile[0].push_back(x2);
                	pile[0].push_back(x3);
                	return true;
		}
		else
		{
			// 查看最后三张
			pile[num].push_front(x1);
			pile[num].pop_back();
			x1 = pile[num].back();
			if( (x1+x2+x3) == 10 || (x1+x2+x3) == 20 || (x1+x2+x3) == 30)
                	{
				pile[num].pop_back();
                        	pile[0].push_back(x1);
                        	pile[0].push_back(x2);
                        	pile[0].push_back(x3);
                        	return true;
					
			}
			else
			{
				pile[num].push_back(x2);	
				pile[num].push_back(x3);
				return false;
			}		
		}		
	}
}


一道纯模拟题,关键在于需要保存和检查每次的牌堆状态,想了很久都觉得直接保存太暴力,没有思路,没做出来。
后来看到http://blog.csdn.net/accelerator_/article/details/38156965
用双端队列来保存牌堆,因为每次只需要查看最多前两张和后两张。
用set来保存状态,这样检查状态的任务就推给set的find函数了,比较巧妙。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值