1. 程式人生 > 其它 >【題解】拉馬車-第八屆藍橋省賽-C組

【題解】拉馬車-第八屆藍橋省賽-C組

STL的佇列和棧

題目介紹

小的時候,你玩過紙牌遊戲嗎?

有一種叫做“拉馬車”的遊戲,規則很簡單,卻很吸引小朋友。

其規則簡述如下:

假設參加遊戲的小朋友是 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;
}