"Accordian" Patience UVA - 127 (风琴牌游戏:栈,模拟习题)

题目链接

题目大意:

模拟玩一个“手风琴”纸牌游戏,规则如下:

按从左至右的顺序发牌,并摆成一行,发牌不要相互重叠。游戏中一旦出现任何一张牌与它左边的第一张或第三张“匹配”,即花色或点数相同,则须立即将其移动到那张牌上面。如果牌被移动后又出现了上述情况,则需再次向左移动。每叠牌只能移动最上面的一张。如果一叠牌被移空,应该立即将右边各叠整体向左移动,补上这个空隙。依次将整副牌都发完,并不断的向左合并。如果全部移动结束后整副牌都放成了一叠,则游戏胜利。

玩上几次你就会遇到一些状况。如果同时有两张牌都可以移动,你应该采取的策略是移动最左边的牌(当然必须是可以移动的)。当一张牌既可以移动到左边第一张,又可以移动到左边第三张时,应移动到左边第三张上面。

分析:

读完题目大家应该可以发现该题为栈的模拟题,因为需要对栈顶进行压入和弹出的操作。

本题需要使用一个二维容器,我使用了vector里面元素为stack<string>,即:vector<stack<string>> boards;

然后进行发牌,可以先使用容器将所有牌存储下来,然后遍历容器发牌。

然后从vector里面的最后一个栈向前判断,此时需要一个辅助指针(一般此类模拟题都需要!!)向前走,走三个来判断前第三个是否符合题意条件。

当k!=j时,我们便可以知道,前面有符合条件的栈,然后对(辅助指针指向的)前面的栈进行压入,对当前的进行弹出,还要判断当前栈是否为空,若为空,将此栈删除。

模拟完毕。

#include <bits/stdc++.h>
using namespace std;
vector<stack<string>> boards;
bool is_match(string s1, string s2) {
    return (s1[0]==s2[0]||s1[1]==s2[1]);
}

int main() {
    freopen("i.txt","r",stdin);
    freopen("o.txt","w",stdout);
    string str;
    while(cin >> str && str!="#") {
        boards.clear();
        vector<string> vec;
        vec.push_back(str);
        getchar();
        getline(cin, str);
        stringstream ss(str);
        string s;
        while(ss>>s) vec.push_back(s);
        getline(cin,str);
        stringstream ss2(str);
        while(ss2>>s) vec.push_back(s);
        for(int i = 0; i < (int)vec.size(); i++) {
            stack<string> st;
            st.push(vec[i]);
            boards.push_back(st);
            for(int j = (int)boards.size()-1, k; j < (int)boards.size(); j++) {//从后向前判断
                //k为辅助指针,判断前面是否又符合条件的栈
                for(s = boards[j].top(), k = j; k > 0; k--) {
                    if(k>=3) {
                        if(is_match(s, boards[k-3].top())) {
                            k-=2;
                            continue;
                        }
                    }
                    if(!is_match(s, boards[k-1].top()))//与前一个和前第三个都不匹配,跳出循环 
                        break;
                }
                if(k!=j) {//与前一个或者前第三个符合任意一个匹配
                    boards[k].push(s);
                    boards[j].pop();
                    if(boards[j].empty())
                        boards.erase(boards.begin()+j);
                    j = k;
                }
            }
        }
        if(boards.size()==1) cout << "1 pile remaining:";
        else cout << boards.size() << " piles remaining:";
        for(int i = 0; i < (int)boards.size(); i++) 
            cout << " " << boards[i].size();
        cout << endl;
    }
    return 0;
}
// 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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值