UVA246 - 10-20-30(队列+ 模拟)

该博客介绍了UVA246题目的解题过程,这是一个关于扑克牌的游戏,目标是通过队列模拟和判断条件寻找和为10、20、30的三张牌。博主分享了解题思路,强调了利用map进行数组判重这一技巧,并提到在特定情况下只会出现和为10、20、30的其中一种情况。
摘要由CSDN通过智能技术生成

题目:UVA246 - 10-20-30(队列+ 模拟)


题目大意:给出52张牌,不分花色,先发七张,形成7堆,然后再从左往右的发牌。如果能够找到三张牌他们的和是10, 20, 30的话,就可以把三张牌按照先后顺序放到你手中的牌的后面。这样一直进行下去,如果你手中有52张牌就赢了,如果你手中没有牌就输了,如果某个状态之前已经出现过,那么就输出draw。然后还要输出总共处理了多少张牌能够得到结果。


解题思路:注意这里不是有三种情况取三张牌,题目貌似保证只会出现这三种中的某一种,这样情况就减少了。然后用队列去模拟,这题学到了一个新的知识点,可以用map来对数组进行判重。


代码:

#include <cstdio>
#include <cstring>
#include <queue>
#include <deque>
#include <vector>
#include <map>

using namespace std;

const int N = 7;

int ans;

struct State {

	int v[N * 10];
	bool operator < (const State &a) const {
		return memcmp (v, a.v, sizeof(State)) < 0;			
	}
};

queue<int> hand;
deque<int> piles[N];
map<State, int> st;

void handle (deque<int>& pile) {

	while (pile.size() >= 3) {

		int n = pile.size();
		if ((pile[0] + pile[1] + pile[n - 1]) % 10 == 0) {

			hand.push(pile[0]);
			hand.push(pile[1]);
			hand.push(pile[n - 1]);
			pile.pop_front();
			pile.pop_front();
			pile.pop_back();
		} else if ((pile[0] + pile[n - 1] + pile[n - 2]) % 10 == 0) {

			hand.push(pile[0]);
			hand.push(pile[n - 2]);
			hand.push(pile[n - 1]);
			pile.pop_front();
			pile.pop_back();
			pile.pop_back();
		} else if ((pile[n - 1] + pile[n - 2] + pile[n - 3]) % 10 == 0) {

			hand.push(pile[n - 3]);
			hand.push(pile[n - 2]);
			hand.push(pile[n - 1]);
			pile.pop_back();
			pile.pop_back();
			pile.pop_back();
		} else
			return;
	}
}

int solve () {

	for (int k = 0; k < 2; k++) {
		for (int i = 0; i < N; i++) {
			piles[i].push_back(hand.front());
			hand.pop();
		}
	}

	ans = 14;
	State tmp;
	while (hand.size()) {

		for (int i = 0; i < N; i++) {
			if (hand.size() == 52)
				return 1;
			if (piles[i].size() == 0)
				continue;
			if (hand.size()) {
				
				piles[i].push_back(hand.front());
				hand.pop();
				ans++;
				handle(piles[i]);
                                //判重
				int cnt = 0;
				memset (tmp.v, 0, sizeof (tmp.v));
				for (int k = 0; k < N; k++) {
					for (int j = 0; j < piles[k].size(); j++)
						tmp.v[cnt++] = piles[k][j];
					tmp.v[cnt++] = 11;
				}

				queue<int> q = hand;
				while (!q.empty()) {
					tmp.v[cnt++] = q.front();
					q.pop();
				}
				tmp.v[cnt] = 11;

				if (st[tmp])
					return -1;
				else
					st[tmp] = 1;
			} else
				return 0;
		}
	}
	return 0;
}

void init () {

	while (!hand.empty()) {
		hand.pop();
	}
	st.clear();
	for (int i = 0; i < N; i++)
		piles[i].clear();
}

int main () {

	int card;
	while (scanf ("%d", &card) && card) {

		init();
		hand.push(card);
		for (int i = 0; i < 51; i++) {

			scanf ("%d", &card);
			hand.push(card);
		}

		int tmp = solve();
		if (tmp == 0)
			printf ("Loss: %d\n", ans);
		else if (tmp == 1)
			printf ("Win : %d\n", ans);
		else
			printf ("Draw: %d\n", ans);
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值