2018 ACM-ICPC 南京网络赛 C.GDY(暴力模拟)

链接:

https://nanti.jisuanke.com/t/30992

题意:

有n个人(标号1-n)玩牌,牌的点数从1-13,其中2>1>13>12>…>3(和斗地主的大小规则相同嘛),告诉你牌池里有哪些牌(含顺序)。
·要求从1号开始,每人一次性摸5张牌以开始游戏,之后按照1、2、3…n、1、2的顺序出牌,开始出牌的人会选择自己最小的牌来出,出牌规则要求只能出比之前打出去的牌大1,或者出最大的一张牌——2,比如上张牌是8,下家就只能接9或者2,出10之类的是非法的。如果一个人没有牌可出,它就会被跳过。
·如果A出牌之后一整轮没有人出牌,那么从A开始,包括A,n个人每个人抽一张牌,然后从A开始,出A最小的牌,以开始下一轮
出牌规则
如果牌取完了,取牌流程取消,其他依旧。
最后,先逃完牌的为Winner,剩下的人计算罚点,为手上所有牌的点数之和。
数据保证每人先取5张牌的流程完之后,n个人手头都有牌(当然最后一个人不一定是5张)

样例输入:

2
2 10
3 5 7 9 11 4 6 8 10 12
3 15
4 5 6 7 8 9 10 11 12 13 2 2 2 2 2

样例输出:

Case #1:
Winner
12
Case #2:
26
55
Winner

思路:

数据规模并不大(For all the test cases, it’s guaranteed that the sum of m doesn’t exceed 4e5.)
作为适合打蓝桥杯水赛的暴力蒟蒻选手- -模拟是长项,所以模拟他们的打牌过程就好了。
流程:将牌池存入一个数组(或者按照题意说的,push入stack,然后每次取用就取top,然后pop)
一个变量cnt表示当前取到的牌的序号。如果cnt == n。然后n人轮流摸5张牌,完了之后从1开始,找自己最小的牌打,2接,3接……直到出现Winner 或者 到某一圈结束,谁都接不了某人出的牌,那么每人摸一张牌,再战……
产生Winner之后,游戏即刻结束,清算积分。

代码:

#include <bits/stdc++.h>
using namespace std;
int a[210][14],b[20010],c[210],n,m,cnt,winner;
inline void get(int id){
    if(cnt < m)a[id][b[cnt++]]++,c[id]++;
}
inline void decrease(int i,int j){
    a[i][j]--,c[i]--;
    if(!c[i])winner = i;
}
void print(){
    for(int i = 0;i < n;i++){
        if(i == winner)puts("Winner");
        else{
            int sum = 0;
            for(int j = 1;j <= 13;j++)sum += j*a[i][j];
            printf("%d\n",sum);
        }
    }
}
int main(){
    int T;
    scanf("%d",&T);
    for(int t = 1;t <= T;t++){
        bool flag = false;
        cnt = 0,winner = -1;
        int id = 0,p = 0,now;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        scanf("%d %d",&n,&m);
        for(int i = 0;i < m;i++)scanf("%d",&b[i]);
        for(int i = 0;i < n;i++)for(int j = 0;j < 5;j++)get(i);
        while(winner == -1){
            if(id == p%n){
                if(flag){
                    for(int i = id;i < n;i++)get(i);
                    for(int i = 0;i < id;i++)get(i);
                }
                flag = true;
                for(int i = 3;i <= 13;i++)
                if(a[id][i]){
                    now = i;
                    decrease(id,now);
                    goto label;
                }
                for(int i = 1;i <= 3;i++)
                if(a[id][i]){
                    now = i;
                    decrease(id,now);
                    goto label;
                }
                label:
                    p++;
            }
            else{
                if(now == 13){
                    if(a[p%n][1]){
                        now = 1;
                        id = p%n;
                        decrease(id,now);
                    }
                    else if(a[p%n][2]){
                        now = 2;
                        id = p%n;
                        decrease(id,now);
                    }
                }
                else if(now != 2){
                    if(a[p%n][now+1]){
                        now++;
                        id = p%n;
                        decrease(id,now);
                    }
                    else if(a[p%n][2]){
                        now = 2;
                        id = p%n;
                        decrease(id,now);
                    }
                }
                p++;
            }
        }
        printf("Case #%d:\n",t);
        print();
    }
    return 0;
}

好菜啊QAQ,文文姐说用goto会被队友打死。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值