2018南京区域资格赛C-GDY

原题传送门

题意:
简单的扑克牌游戏,先定义扑克牌的大小如下:

  • 3<4<5<6<7<8<9<10<11<12<13<1<2<11<12<13<1<2.

然后从第一个开始出最小的牌,然后其余玩家接着出牌,谁先没有手牌谁就获胜,并输出其余人的手牌点数和
出牌规则:

  1. 一开局从第一位玩家开始每人抽取5张牌,保证第一位玩家回合开始前每人手牌数不低于1张
  2. 玩家a出了一张2的话,从玩家a开始,所有人按顺序从牌堆抽取1张牌,然后玩家a出一张最小的牌
  3. 玩家出的牌必须得是上一张打出的牌的点数+1,否则可以选择出一张2,若是前面两种牌都没有,则跳过该玩家回合
  4. 如果所有的玩家的回合都被跳过(即上一张打出的牌为b,而所有的玩家都没有b+1的牌或者是2的牌)则从最后一个出牌的玩家开始,所有的玩家都需要从牌堆里面抽取1张牌,并出一张最小的牌
  5. 若是牌堆里面已经没有牌了,则忽略抽牌操作

思路:
其实难点在于题意,题意里面描述的是只要前面的玩家(我就理解成了上一个玩家,但实际上是上一个出牌的玩家)没有打出2,那么这个玩家就可以打出2...看了别人的AC代码才发现自己题意读错了.读懂了题意之后直接模拟即可

AC代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 2e2 + 10, M = 2e4 + 10;

multiset<int>a[N];//3~13, 1
int b[M], cnt = 0, pre;
int n, m, T, ans[N];
int num[N];//2

void draw(int man)
{//抽牌
    if(cnt >= m)        return ;
    if(b[cnt] == 15)    num[man] ++;
    else                a[man].insert(b[cnt]);
    cnt ++;
}

bool play(int man)
{//根据上一张牌的出牌
    if(a[man].find(pre) != a[man].end())
        a[man].erase(a[man].find(pre));
    else
        num[man] --, pre = 15;
    return num[man] + a[man].size() > 0;
}

bool first(int man)
{//开局式出牌
    if(a[man].size())
    {
        pre = *a[man].begin();
        a[man].erase(a[man].begin());
    }
    else    num[man] --, pre = 15;
    return  num[man] + a[man].size() > 0;
}

int main()
{
//  freopen("1.txt", "r", stdin);
    scanf("%d", &T);
    for(int ca = 1; ca <= T; ca ++)
    {
        memset(num, 0, sizeof num);
        cnt = 0;

        scanf("%d%d", &n, &m);
        for(int i = 0; i < m; i ++)
        {
            scanf("%d", b + i);
            if(b[i] < 3)    b[i] += 13;//1, 2 -> 14, 15
        }

        printf("Case #%d:\n", ca);
        for(int i = 0; i < n; i ++)
            for(int j = 0; j < 5; j ++)
                draw(i);

        int man = 0;
        bool flag = first(0);

        while(flag)
        {
            if(pre == 15)
            {
                for(int i = 0; i < n; i ++, man = (man + 1) % n)
                    draw(man);
                flag = first(man);
            }
            else
            {
                pre ++;
                man = (man + 1) % n;
                int i;
                for(i = 1; i < n; i ++, man = (man + 1) % n)
                    if(a[man].find(pre) != a[man].end() || num[man])
                    {
                        flag = play(man);
                        break;
                    }
                if(i == n)  pre = 15;//抽牌
            }
        }

        for(int i = 0; i < n; i ++)
        {
            ans[i] = num[i] * 2;
            while(!a[i].empty())
            {
                int t = *a[i].begin();
                if(t == 14) t = 1;
                ans[i] += t;
                a[i].erase(a[i].begin());
            }
            if(ans[i])  printf("%d\n", ans[i]);
            else        puts("Winner");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_38287798/article/details/82355182