hpu 1454: 接竹竿 (c++ queue 的运用)

问题:

一个人玩起了接竹竿。

规则是,当一个人出的牌在上面的牌中有一样数字的,则他可以将这两个牌和两牌之间的牌拿走,然后出一张扑克。

左手先出牌,所赢的牌是按照以前的顺序出的。

比如:左手剩了1,2两张牌,上一步赢了一次,是2,3,4,2 那么他的出牌顺序就是1,2,2,3,4,2。

当一个人手中没牌时,则另一个人胜利。

输入:

第一行一个数T,玩了T次

每次游戏开始是一个数n,只用了数字 <=n 的扑克,

后面有两行数字,每行有 2*n 个数,

第一行代表左手的扑克。

第二行代表右手的扑克。

1 <= T <= 10

1 <= n <= 13

输出:

对于每次游戏,输出游戏的结果,

(左右手累积出牌十万次不分输赢)

每次游戏输出占一行,

左手赢输出1,

右手赢输出2,

平局输出0

分析:

左手,右手的 牌,可以分别 用一个队列来记录,方便从前删除,从后插入,以及判断是否为空。

打出去的牌可以用一个数组记录。

如果不懂 队列的 定义,可以看看。

我写的 《queue 初探》

代码:

#include<queue>
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std;    //左手先出牌
int main()
{
    int T;
    cin>>T;                    //输入T
    while (T--)
        {
        int n,a;               //用点数<=n的扑克牌  ,每个手有数量为2n的牌

        int ping[20];        //  这个数组用来记录  左右手 已经出的牌

        int lp,step;
        cin>>n;                   //输入n
        queue<int> left,right;    //定义  左  右 两个队列。

        for (int i=0;i<2*n;i++)      // 左手的 2n 张牌
        {
            cin>>a;
            left.push(a);            // 从后面向队列中插入元素
        }


        for (int i=0;i<2*n;i++)      // 右手的  2n 张牌
        {
            cin>>a;
            right.push(a);           // 从后面向队列中插入元素
        }
 
        step = 0;          //记录出牌的次数
        lp = 0;            //lp是用来记录 已经出的牌的序号

        int man=1;       //  man 是用来 帮助 判断是 左手,还是右手出牌的变量。。

        int ans = 0 ;        //  判断输赢的变量,平局为0  ,左赢为1,  右赢为2

        while (step<100000)
        {
            if (man%2==1)
            {                                       //先左手出牌
                while (true)
                {
                    step++;
                    ping[lp++] = left.front();      //记录左手出的牌
                    left.pop();                     //左手的牌 删去 最上面的一个
                    bool fafe = true;               //
                    for (int i=0;i<lp-1;i++)
                    {
                        if (ping[i]==ping[lp-1])       //ping[lp-1] 是刚刚出的牌。开始判断左手出的牌是否与前面的相同
                        {
                            fafe = false;
                            for (int j=i;j<lp;j++)     //如果有相同的,就把中间这些牌都加到 left 队的后面。
                                left.push(ping[j]);

                            lp = i;                    // 因为从 i 号牌拿走,所以下次发牌 的序号是第 i 个。
                            break;
                        }
                    }
                    if (fafe)
                        break;                 // 如果有相同的,就跳出循环
                } 
                if (left.empty())            //   如果 left 空
                {
                    ans = 2;                   // 右赢
                    break;
                }
                man^=1;       //  ^ 异或 运算,相同为 0,不同为 1.。。能走到这一步,说明没有相同的。man变成0
            }                  //  那么下一次循环就从右手开始


            else                 //右手 (同左手)
            {
                 while (true)
                {
                    step++;
                    ping[lp++] = right.front();
                    right.pop();
                    bool fafe = true;
                    for (int i=0;i<lp-1;i++)
                    {
                        if (ping[i]==ping[lp-1]){
                            fafe = false;
                            for (int j=i;j<lp;j++)
                                right.push(ping[j]);
                            lp = i;
                            break;
                        }
                    }
                    if (fafe) break;
                }
                if (right.empty())    // 如果右手 空,左赢。
                {
                    ans = 1;
                    break;
                }
                man^=1;        //能走到这一步,说明没有相同的。man变成 1 .那么下次循环,就从左手开始
        }
    }
        if (step>=100000)
        {
            ans = 0;          // 10万次出牌没有胜负,为平局
            cout<<ans<<endl;
        }
        else
        {
            cout<<ans<<endl;
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_41003528/article/details/78887161
今日推荐