一道朴素的模拟题,有几个地方还是可以留意:
1、一个牌堆的牌全部清空后,牌堆要被移除。我第一反应是链表,不过链表弄起来确实麻烦,其实用vector只要用一个while循环在发牌的时候判断一下牌堆是否为空,为空就挪到下一位就可以了。
2、不必分别判断10、20、30。因为面值最大是10,所以三张牌最多就30。那么只需要判断面值的和除以10的余数是否为零即可
3、关于平局的判断:我用了一个感觉很笨重的方法:自定义了一个struct来储存每次发牌时的快照,并把这些快照装在了一个vector中。感觉应该有更好的办法
Run Time: 0.142s
// UVa #6-10.246.cpp
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<stack>
#include<vector>
#include<queue>
#define maxn 500
using namespace std;
struct Status{
vector<int> pilestatus[7];
queue<int> deckstatus;
Status(vector<int> p[7], queue<int> q):deckstatus(q){
for(int i = 0; i < 7; i ++) pilestatus[i] = p[i];
}
bool operator == (const Status& s) const {
if(s.deckstatus.size() != deckstatus.size()) return false;
for(int i = 0; i < 7; i ++) {
if(s.pilestatus[i].size() != pilestatus[i].size()) return false;
for(int j = 0; j < pilestatus[i].size(); j ++) {
if(s.pilestatus[i][j] != pilestatus[i][j]) return false;
}
}
queue<int> tempdeckstatus = deckstatus;
queue<int> stempdeckstatus = s.deckstatus;
while(!tempdeckstatus.empty()) {
if(tempdeckstatus.front() != stempdeckstatus.front()) return false;
tempdeckstatus.pop(); stempdeckstatus.pop();
}
return true;
}
};
//Global Variables.
queue<int> deck;
vector<int> piles[7];
int p, cnt;
vector<Status> statuses;
/
void printPiles();
void clear(queue<int>& q) {
queue<int> empty;
swap(q,empty);
}
void checkPile(vector<int>& pile) {
if(pile.size() >= 3) {
if((pile[0] + pile[1] + pile[pile.size()-1]) % 10 == 0) {
deck.push(pile[0]);
deck.push(pile[1]);
deck.push(pile[pile.size()-1]);
for(int i = 0; i < pile.size()-3; i ++) //Move the subsequent cards 2 pos up
pile[i] = pile[i+2];
pile.resize(pile.size()-3);
checkPile(pile);
}
else if((pile[0] + pile[pile.size()-2] + pile[pile.size()-1]) % 10 == 0) {
deck.push(pile[0]);
deck.push(pile[pile.size()-2]);
deck.push(pile[pile.size()-1]);
for(int i = 0; i < pile.size()-3; i ++)
pile[i] = pile[i+1];
pile.resize(pile.size()-3);
checkPile(pile);
}
else if((pile[pile.size()-3] + pile[pile.size()-2] + pile[pile.size()-1]) % 10 == 0) {
deck.push(pile[pile.size()-3]);
deck.push(pile[pile.size()-2]);
deck.push(pile[pile.size()-1]);
pile.resize(pile.size()-3);
checkPile(pile);
}
}
}
int deal() {
int i, card;
for(i = 0; i < 7; i ++, cnt ++) {
card = deck.front(); deck.pop();
piles[i].push_back(card); //Initial Deck.
}
p = -1;
while(1) {
Status curStatus = Status(piles, deck);
for(int i = 0; i < statuses.size(); i ++) //If current status occured before, game's draw
if(curStatus == statuses[i]) return 0;
statuses.push_back(curStatus); //Record current status.
card = deck.front(); deck.pop(); //Retrieve the card to be dealt.
do{p = (p+1)%7;}while((piles[p]).size() == 0); //Skip empty piles, locate the pile to be dealt.
vector<int>& curPile = piles[p];
curPile.push_back(card); //Deal the card.
cnt ++;
checkPile(curPile); //Check and pick cards from the dealt pile.
if(deck.size() == 52) return 1; //No piles remaining, game's won.
if(deck.empty()) return -1; //Deck empty, game's lost.
}
return -2;
}
int main() {
int card;
while(scanf("%d", &card) && card) {
clear(deck);
statuses.clear();
for(int i = 0; i < 7; i ++)
piles[i].clear();
p = cnt = 0;
deck.push(card);
//Get Deck.
for(int i = 0; i < 51; i ++) {
scanf("%d",&card);
deck.push(card);
}
//Deal.
int result = deal();
if(result == 0)
printf("Draw: %d\n", cnt);
else if(result == 1)
printf("Win : %d\n", cnt);
else if(result == -1)
printf("Loss: %d\n", cnt);
}
return 0;
}