hihocoder 1531 德国心脏病 (模拟)

描述

Jack在和朋友们玩德国心脏病。

德国心脏病的游戏牌分为水果牌和动物牌。水果只有4种:香蕉、草莓、樱桃、柠檬,每张水果牌上会有种类不定、总数目1-5的水果;动物只有3种:猴子、大象、猪,每张动物牌上有且仅有一只动物。

n名玩家绕圈就座,第一轮游戏从0号至n-1号轮流出牌。每个玩家面前最多只有一张牌,如果玩家出牌时,他的面前已经摆放了一张牌,他新出的牌将会严丝合缝地盖住旧牌。

任何时候玩家可以选择按铃操作。如果按铃成功,玩家可以获得当前场上所有牌(包括被盖住的牌)并进入下一轮游戏,下一轮游戏由他先出牌,然后依序轮流出牌;否则,他需要支付给每位玩家一张手牌,然后他成为下一位出牌者,继续这一局游戏。

按铃成功的条件:

1、当前场上(被盖住的牌不算,以下同)某种水果的数量正好为5。

2、当前场上出现猴子,至少有一个水果,且没有出现柠檬。

3、当前场上出现大象,至少有一个水果,且没有出现草莓。

4、当前场上出现猪,且至少有一个水果。

Bob对这个游戏很感兴趣,他给了Jack一个操作序列,希望Jack输出最终每个人拥有的牌的数量。每名玩家初始拥有10,000,000张牌。操作分为两种:出牌或按铃。操作结束时游戏立即终止。

1、出牌的格式是:Fruit+水果数s+水果种类s,0、1、2、3分别表示香蕉、草莓、樱桃、柠檬。如Fruit 4 0 2 2 2代表1个香蕉和3个樱桃的牌。或Animal+动物种类,0、1、2分别代表猴子、大象、猪。如Animal 0代表一张猴子牌。注意,选手需要自己计算出牌者是几号玩家。

2、按铃的格式是:Ring+选手编号。如Ring 2。

 

输入

第一行两个正整数n(≤10), k(≤100,000)。

接下来k行,每行对应一个操作。

 

输出

n行,每行一个整数,代表每个玩家游戏结束后拥有的牌的数目。

 

样例解释

3 13                # 井号后为样例输入说明:3名玩家,13次操作
Fruit 5 0 0 0 0 0   # 0号玩家出牌:5个香蕉
Ring 0              # 0号玩家按铃:按铃成功,获得场上的1张牌,开始下一轮游戏
Ring 1              # 1号玩家按铃:按铃失败,给0, 2号玩家各一张牌
Fruit 3 3 0 0       # 1号玩家出牌:1个柠檬+2个香蕉
Animal 0            # 2号玩家出牌:猴子
Fruit 4 2 2 2 2     # 0号玩家出牌:4个樱桃
Ring 2              # 2号玩家按铃:按铃失败,给0, 1号玩家各一张牌
Fruit 3 0 0 0       # 2号玩家出牌:3个香蕉,盖住上一张牌【猴子】
Fruit 2 0 0         # 0号玩家出牌:2个香蕉,盖住上一张牌【4个樱桃】
Ring 2              # 2号玩家按铃:按铃失败,给0, 1号玩家各一张牌
Animal 2            # 2号玩家出牌:猪,盖住上一张牌【3个香蕉】
Ring 0              # 0号玩家按铃:按铃成功,获得场上的6张牌,开始下一轮游戏
Animal 2            # 0号玩家出牌:猪,游戏终止

 

样例输入

3 13
Fruit 5 0 0 0 0 0
Ring 0
Ring 1
Fruit 3 3 0 0
Animal 0
Fruit 4 2 2 2 2
Ring 2
Fruit 3 0 0 0
Fruit 2 0 0
Ring 2
Animal 2
Ring 0
Animal 2

 

样例输出

10000006
9999999
9999994

 

思路

算一道模拟题吧,照着题意实现每一个步骤便可以了。

 

AC 代码

#include <iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=15;
int num[N];                 //第i个玩家前面牌的数目
int ans[N];                 //玩家剩余牌的数量
int data[7];                //当前场上水果以及动物的数量 [0,3] 水果 [4,6] 动物
int now;                    //当前出牌玩家
int lastdata[N][7]; //玩家 i 在第几步时候出牌状态
int n,k;

void init()
{
    memset(num,0,sizeof(num));
    memset(data,0,sizeof(data));
    memset(lastdata,0,sizeof(lastdata));
}

bool jud()
{
    for(int i=0; i<4; i++)
        if(data[i]==5)return true;
    if((data[0]||data[1]||data[2])&&!data[3]&&data[4])return true;
    if((data[0]||data[2]||data[3])&&!data[1]&&data[5])return true;
    if((data[0]||data[1]||data[2]||data[3])&&data[6])return true;
    return false;
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n>>k)
    {
        int x1,x2;
        char op[10];
        init();
        now=0;
        for(int i=0; i<n; i++)
            ans[i]=10000000;
        for(int ki=0; ki<k; ki++)
        {
            cin>>op;
            if(op[0]=='R')
            {
                cin>>x1;
                if(jud())       //按铃成功
                {
                    int cnum=0;
                    for(int i=0; i<n; i++)  //获得场上所有牌
                        cnum+=num[i];
                    init();
                    ans[x1]+=cnum;
                }
                else
                {
                    for(int i=0; i<n; i++)  //分给其他人牌
                        ans[i]++;
                    ans[x1]-=n;
                }
                now=x1;
            }
            else
            {
                cin>>x1;
                for(int i=0; i<7; i++)      //覆盖最顶端的牌
                    data[i]-=lastdata[now][i];
                num[now]++;
                memset(lastdata[now],0,sizeof(lastdata[now]));
                if(op[0]=='F')
                {
                    for(int i=0; i<x1; i++) //水果
                    {
                        cin>>x2;
                        lastdata[now][x2]++;
                        data[x2]++;
                    }
                }
                else                        //动物
                {
                    lastdata[now][4+x1]++;
                    data[4+x1]++;
                }
                ans[now]--;
                now=(now+1)%n;
            }
        }
        for(int i=0; i<n; i++)
            cout<<ans[i]<<endl;
    }
    return 0;
}