``Accordian'' Patience |
You are to simulate the playing of games of ``Accordian'' patience, the rules for which are as follows:
Deal cards one by one in a row from left to right, not overlapping. Whenever the card matches its immediate neighbour on the left, or matches the third card to the left, it may be moved onto that card. Cards match if they are of the same suit or same rank. After making a move, look to see if it has made additional moves possible. Only the top card of each pile may be moved at any given time. Gaps between piles should be closed up as soon as they appear by moving all piles on the right of the gap one position to the left. Deal out the whole pack, combining cards towards the left whenever possible. The game is won if the pack is reduced to a single pile.
Situations can arise where more than one play is possible. Where two cards may be moved, you should adopt the strategy of always moving the leftmost card possible. Where a card may be moved either one position to the left or three positions to the left, move it three positions.
Input data to the program specifies the order in which cards are dealt from the pack. The input contains pairs of lines, each line containing 26 cards separated by single space characters. The final line of the input file contains a # as its first character. Cards are represented as a two character code. The first character is the face-value (A=Ace, 2-9, T=10, J=Jack, Q=Queen, K=King) and the second character is the suit (C=Clubs, D=Diamonds, H=Hearts, S=Spades).
One line of output must be produced for each pair of lines (that between them describe a pack of 52 cards) in the input. Each line of output shows the number of cards in each of the piles remaining after playing ``Accordian patience'' with the pack of cards as described by the corresponding pairs of input lines.
QD AD 8H 5S 3H 5H TC 4D JH KS 6H 8S JS AC AS 8D 2H QS TS 3S AH 4H TH TD 3C 6S 8C 7D 4C 4S 7S 9H 7C 5D 2S KD 2D QH JD 6D 9D JC 2C KH 3D QC 6C 9S KC 7H 9C 5C AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC AD 2D 3D 4D 5D 6D 7D 8D TD 9D JD QD KD AH 2H 3H 4H 5H 6H 7H 8H 9H KH 6S QH TH AS 2S 3S 4S 5S JH 7S 8S 9S TS JS QS KS #
6 piles remaining: 40 8 1 1 1 1 1 pile remaining: 52
题目大意:
你的任务是模拟一种叫「Accordian」的纸牌游戏,他的游戏规则如下:
(1) 一副扑克牌有52张牌,首先把纸牌一张一张由左到右排好(不能有重叠,所以共有52堆牌,每堆一张),当某一张牌与他左边那张牌或者左边的第三张牌有「Match」的时候,就把这张牌移到那张牌上面去。
(2) 在这里两张牌「Match」指的是这两张牌的花色(suit)或者点数(rank)一样。
(3) 当你做了一个移动之后,要察看是否还可以做其他的移动。
(4) 在任何时间,只有最上面那张牌可以被移动。
(5) 如果因为移动一张牌使得产生一个空格(也就是被移动的那堆牌只有一张牌),你必须把右边所有的牌堆往左移一格。
(6) 如此不断的寻找可移动的牌,直到没有一张牌可以移动游戏就结束了。
(7)在选择可以移动的牌的时候可能有些状况会发生。
如果有两张牌都可以移动,你应该要移动最左边的那张牌。
当一张牌可以被移动到左边一格,或左边三格的时候,你必须移动到左边三格。
Input
输入包含多组测试资料。每组测试资料两列,每列有26张牌。
每张牌以2个字元代表。第一个字元代表牌的点数(A=Ace, 2~9, T=10, J=Jack, Q=Queen, K=King),第二个字元代表牌的花色(C=Clubs, D =Diamonds, H=Hearts, S=Spades)
若遇到仅含#的一列代表输入结束。
Output
对每组测试资料输出游戏结束时剩下几堆牌,以及每堆牌有多少张牌。请注意如果只有1堆牌,pile后没有加s,请参考Sample Output。
解题思路:
这题主要用到的是堆栈的思想,如果一张牌可以移动的话,就将改位置的栈顶,压进可移动的位置,再将栈顶弹出。
如果遇到空的栈就将该位置后面的数组,右移补全。
#include <iostream> #include <stack> #include <string> #include <stdio.h> using namespace std; struct Card{ char rank[3]; }; const int N = 52; Card card[N]; bool match(Card a,Card b) { return a.rank[0] == b.rank[0] || a.rank[1] == b.rank[1]; } int main() { while(1) { stack<Card> st[N]; cin >> card[0].rank; if(card[0].rank[0] == '#') break; st[0].push(card[0]); for(int i = 1;i < N; i++) { cin >> card[i].rank; st[i].push(card[i]); } int n = N; for(int i = 0;i < n; i++) { if(i >= 0 && st[i].empty()) { for(int j = i;j < n - 1; j++) { st[j] = st[j+1]; } n--; i--; continue; } if(i - 3 >= 0 && match(st[i].top(),st[i-3].top())) { st[i-3].push(st[i].top()); st[i].pop(); i -= 4; continue; } if(i - 1 >= 0 && match(st[i].top(),st[i-1].top())) { st[i-1].push(st[i].top()); st[i].pop(); i -= 2; continue; } } if(n == 1) cout<<n<<" pile remaining: "; else cout<<n<<" piles remaining: "; for(int i=0;i<n-1;i++) { cout<<st[i].size()<<" "; } cout<<st[n-1].size(); cout<<endl; } return 0; }