ACM-ICPC 2018 南京赛区网络预赛 - GDY(模拟)

ACM-ICPC 2018 南京赛区网络预赛 - GDY

题意:

有 n 个人 m 张牌,牌的编号从1~13,其大小顺序为 3 < 4 < ... < 12 < 13 < 1 < 2

在游戏开始时,每个人先从牌堆中抽取5张牌(五张五张抽),题目保证在初始抽牌结束时每个人手中至少有一张牌

然后从第一个人开始,他会取出手牌中最小的牌,并打出,接下来第二个人要出的牌必须为下一张牌,如第一个人出4下一个人须出5,也可以出2,2可以吃除了2的任何牌,但手牌中有下一张牌和2时,优先出下一张牌。

当第 i 个人出牌后其余人都无法出牌则所有人从牌库中抽一张牌,若牌库空了则跳过,然后第 i 个人继续出牌,出其手中最小的牌。

模拟整个游戏过程即可

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
const int N = 2e4 + 10;
int T, n, m, a[N], c[222][15], cnt[222];
int get_min(int pos) { //找到手牌最小
    int i = 0;
    for(i=3;i<=14;i++) if(c[pos][i]) break;
    if(i == 15 && c[pos][2]) i = 2;
    return i;
}
int main()
{
    scanf("%d", &T); int cas = 0;
    while(T--) {
        memset(c, 0, sizeof c);
        memset(cnt, 0, sizeof cnt);
        scanf("%d%d", &n, &m);
        int l = 1; // 牌顶位置
        for(int i=1;i<=m;i++) {
            scanf("%d", &a[i]);
            if(a[i] == 1) a[i] = 14;
        }
        for(int i=1;i<=n;i++) { // 初始抽牌
            for(int j=1;j<=5;j++) {
                if(l<=m) c[i][a[l++]] ++, cnt[i] ++;
            }
        }
        int pre = 0, pos = 1, last = 0;
        while(true) {
            if(pos == last) { // 其他人均无法出牌
                for(int i=0;i<n;i++){
                    if(l <= m) { //所有人均抽一张牌
                        int to = pos + i; if(to > n) to -= n;
                        c[to][a[l++]] ++; cnt[to] ++;
                    }
                }
                pre = 0;
            }
            if(pre == 0) { // 第一张出牌
                int i = get_min(pos);
                c[pos][i] --; pre = i; cnt[pos] --; last = pos;
            } else {
                if(pre == 2 || c[pos][pre+1] == 0) {
                    if(pre != 2 && c[pos][2]) {
                        c[pos][2] --; pre = 2; cnt[pos] --; last = pos;
                    }
                } else {
                    c[pos][pre+1] --; cnt[pos] --; pre ++; last = pos;
                }
            }
            if(cnt[pos] == 0) break;
            if(++pos > n) pos -= n; 
        }
        printf("Case #%d:\n", ++cas);
        for(int i=1;i<=n;i++) {
            int sum = 0; c[i][1] = c[i][14];
            for(int j=1;j<=13;j++) sum += j * c[i][j];
            if(sum == 0) puts("Winner");
            else printf("%d\n", sum);
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值