【題解】拉馬車-第八屆藍橋省賽-C組
題目介紹
小的時候,你玩過紙牌遊戲嗎?有一種叫做“拉馬車”的遊戲,規則很簡單,卻很吸引小朋友。
其規則簡述如下:
假設參加遊戲的小朋友是 A 和 B,遊戲開始的時候,他們得到的隨機的紙牌序列如下:
A 方:[K,8,X,K,A,2,A,9,5,A] B 方:[2,7,K,5,J,5,Q,6,K,4] 其中的 X 表示 “10”,我們忽略了紙牌的花色。
從 A 方開始,A、B 雙方輪流出牌。
當輪到某一方出牌時,他從自己的紙牌佇列的頭部拿走一張,放到桌上,並且壓在最上面一張紙牌上(如果有的話)。
此例中,遊戲過程:
A 出 K,B 出 2,A 出 8,B 出 7,A 出 X,此時桌上的序列為:
K,2,8,7,X 當輪到 B 出牌時,他的牌 K 與桌上的紙牌序列中的 K 相同,則把包括 K 在內的以及兩個 K 之間的紙牌都贏回來,放入自己牌的隊尾。
注意:為了操作方便,放入牌的順序是與桌上的順序相反的。
此時,A、B 雙方的手裡牌為:
A 方:[K,A,2,A,9,5,A] B 方:[5,J,5,Q,6,K,4,K,X,7,8,2,K] 贏牌的一方繼續出牌。
也就是 B 接著出 5,A 出 K,B 出 J,A 出 A,B 出 5,又贏牌了。
5,K,J,A,5 此時雙方手裡牌:
A 方:[2,A,9,5,A] B 方:[Q,6,K,4,K,X,7,8,2,K,5,A,J,K,5] 注意:更多的時候贏牌的一方並不能把桌上的牌都贏走,而是拿走相同牌點及其中間的部分。
但無論如何,都是贏牌的一方繼續出牌,有的時候剛一出牌又贏了,也是允許的。
當某一方出掉手裡最後一張牌,但無法從桌面上贏取牌時,遊戲立即結束。
對於本例的初始手牌情況下,最後 A 會輸掉,而 B 最後的手裡牌為:
9K2A62KAX58K57KJ5 本題的任務就是已知雙方初始牌序,計算遊戲結束時,贏的一方手裡的牌序。
當遊戲無法結束時,輸出 −1。
輸入格式:
輸入為 2 行,2 個串,分別表示 A、B 雙方初始手裡的牌序列。
輸入的兩個串的長度都不超過 30, 保證兩人是拿一副牌玩的,所以總牌數不超過 52 張,且同一種牌最多隻有 4 張。 公平起見,開始時兩人手中的牌數相等。
輸出格式:
輸出為 1 行,1 個串,表示 A 先出牌,最後贏的一方手裡的牌序。
輸入樣例:
96J5A898QA
6278A7Q973
輸出樣例:
2J9A7QA6Q6889977
分析與程式碼實現
主要利用了STL中的棧和佇列
- 用一個棧維護牌堆
- 用兩個佇列維護A,B雙方的手牌
- 用一個狀態變數記錄當前的輪次(該誰出牌)
- 當輪到A出牌但A手中無牌(佇列A長度為零)時B獲勝
- 當輪到B出牌但B手中無牌(佇列B長度為零)時A獲勝
C++程式碼實現
#include <stack>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
string s1, s2;
queue<char> q1, q2;
stack<char> st;
map<char, int> mp;
int main(){
cin >> s1 >> s2;
for (int i = 0; i < s1.size(); i++) q1.push(s1[i]);
for (int i = 0; i < s2.size(); i++) q2.push(s2[i]);
int flag = 1, cnt = 0;
while(1){
cnt++;
//flag==1時為people1的輪次
if(flag && q1.empty()) break;
if(!flag && q2.empty()) break;
if(flag){
char a = q1.front();
q1.pop();
if(mp[a]){
q1.push(a);
while(st.top()!=a){
q1.push(st.top());
mp[st.top()]--,st.pop();
}
q1.push(st.top());
mp[st.top()]--, st.pop();
flag = !flag;
}
else
st.push(a), mp[a]++;
if(q1.empty()) break;
}
else{
char a = q2.front();
q2.pop();
if(mp[a]){
q2.push(a);
while(st.top()!=a){
q1.push(st.top());
mp[st.top()]--, st.pop();
}
q2.push(st.top());
mp[st.top()]--, st.pop();
flag = !flag;
}
else
st.push(a), mp[a]++;
if(q2.empty()) break;
}
flag = !flag;
}
if(q1.empty()){
while(!q2.empty()){
cout << q2.front();
q2.pop();
}
}
else if(q2.empty()){
while(!q1.empty()){
cout << q1.front();
q1.pop();
}
}
cout << endl;
return 0;
}