2018 ICPC北京网络赛 C. Cheat (模拟)

题目链接

恶心的大模拟……

4个人打牌轮流出牌(当前轮次应出的牌按照A-K顺序循环),同时声明所出的牌,且这个声明可能为假,出牌后其他人可以选择质疑他的声明。质疑时,若当前声明为真,质疑者拿走桌面上所有牌,否则出牌者拿走桌面上所有牌。第一个出完手中所有牌的人赢。

出牌的规则:

玩家1:如果能放,放一张;否则放一张字典序最小的。

玩家2:如果能放,全部放下;否则放一张字典序最小的。

玩家3:如果能放,全部放下;否则选择牌数最小且字典序最小的牌,全部放下。

玩家4:对于这一轮应该放的牌,全部放下。如果数目小于3,再额外放一张字典序最小的。

质疑的规则:

玩家1:如果当前声明牌数+声明的牌在玩家1手中的数目>4 或者 下一轮是玩家1出牌且他的声明必为假,则选择质疑。

玩家2:如果下一轮是玩家2出牌且他的声明必为假,则选择质疑。

玩家3:如果玩家3持有4张当前声明的牌,则选择质疑。

玩家4:如果出牌者此时手中为空,则选择质疑。

需要注意的细节:

1.如果某一轮没有发生质疑,桌上的牌不会清空,在下一次质疑的时候才会清空。

2.字典序K<Q。

3.玩家3放牌剔除牌数为0,玩家4放牌要判断是否冲突。

 

丑陋的代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1050;
const ll INF = (1LL << 62) - 1;
const ll mod = 998244353;
const double eps = 1e-8;

int num[1050][1050], leg[1050];
int tmp, tmpb, no, nob;
int pos, now, Win;
char s[1050];
char str[1050] = {"A23456789#JQK"};
int res[1000050], N;

bool check1(int now, int pos)
{
    int Now = now;
    if(now > 13) Now -= 13;
    if(num[pos][Now]) return 1;
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]])
            return 0;
    }
    return 1;
}

bool check2(int now, int pos)
{
    int Now = now;
    if(now > 13) Now -= 13;
    if(num[pos][Now]) return 1;
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]])
            return 0;
    }
    return 1;
}

int judge1(int now, int pos)
{
    tmp = 1;
    if(num[pos][now]) {no = now; return 1;}
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]])
        {
            no = leg[i];
            return 2;
        }
    }
    return 0;
}

int judge2(int now, int pos)
{
    if(num[pos][now]) {tmp = num[pos][now]; no = now; return 1;}
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]])
        {
            no = leg[i];
            tmp = 1;
            return 2;
        }
    }
    return 0;
}

int judge3(int pos)
{
    if(num[pos][now]) {tmp = num[pos][now]; no = now; return 1;}
    int minn = 1000, k;
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]] > 0 && num[pos][leg[i]] < minn)
        {
            minn = num[pos][leg[i]];
            k = leg[i];
        }
    }
    if(minn < 1000) {tmp = minn; no = k; return 2;}
    return 0;
}

int judge4(int pos)
{
    if(num[pos][now] >= 3) {tmp = num[pos][now]; no = now; return 1;}
    tmp = num[pos][now], no = now;
    for(int i = 1;i <= 13;i++)
    {
        if(num[pos][leg[i]])
        {
            if(tmp && no == leg[i]) continue;
            nob = leg[i];
            tmpb = 1;
            break;
        }
    }
    if(!tmp && !tmpb) return 0;
    if(tmp && !tmpb) return 1;
    return 2;
}

bool Empty(int x)
{
    for(int i = 1;i <= 13;i++)
        if(num[x][i]) return false;
    return true;
}

void getnum(int x)
{
    for(int i = 0;i < N;i++)
        num[x][res[i]]++;
    N = 0;
}

int main()
{
    for(int i = 1;i <= 13;i++) leg[i] = i;
    leg[10] = 1, leg[1] = 10;
    leg[13] = 12, leg[12] = 13;
    while(~scanf("%s", s))
    {
        memset(num, 0, sizeof(num));
        if(s[0] == '1') num[1][10]++;
        else if(s[0] >= '0' && s[0] <= '9') num[1][s[0]-'0']++;
        else if(s[0] == 'J') num[1][11]++;
        else if(s[0] == 'Q') num[1][12]++;
        else if(s[0] == 'A') num[1][1]++;
        else num[1][13]++;
        for(int i = 1;i <= 12;i++)
        {
            scanf("%s", s);
            if(s[0] == '1') num[1][10]++;
            else if(s[0] >= '0' && s[0] <= '9') num[1][s[0]-'0']++;
            else if(s[0] == 'J') num[1][11]++;
            else if(s[0] == 'Q') num[1][12]++;
            else if(s[0] == 'A') num[1][1]++;
            else num[1][13]++;
        }
        for(int i = 2;i <= 4;i++)
        {
            for(int j = 1;j <= 13;j++)
            {
                scanf("%s", s);
                if(s[0] == '1') num[i][10]++;
                else if(s[0] >= '0' && s[0] <= '9') num[i][s[0]-'0']++;
                else if(s[0] == 'J') num[i][11]++;
                else if(s[0] == 'Q') num[i][12]++;
                else if(s[0] == 'A') num[i][1]++;
                else num[i][13]++;
            }
        }
        pos = 1, now = 1, Win = 0;
        N = 0;
        int noo = 1;
        while(1)
        {
            if(Empty(1) || Empty(2) || Empty(3) || Empty(4)) break;
            if(pos == 1)
            {
                int tp = judge1(now, 1);
                if(!tp) {Win = 1;break;}
                num[pos][no]--;
                res[N++] = no;
                if(!check2(now+1, 2))
                {
                    if(tp == 1) getnum(2);
                    else getnum(pos);
                }
                else if(num[3][now] == 4)
                {
                    if(tp == 1) getnum(3);
                    else getnum(pos);
                }
                else if(Empty(pos))
                {
                    if(tp == 1) getnum(4);
                    else getnum(pos);
                }
            }
            else if(pos == 2)
            {
                int tp = judge2(now, 2);
                if(!tp) {Win = 2;break;}
                for(int j = 0;j < tmp;j++)
                {
                    res[N++] = no;
                    num[pos][no]--;
                }
                if(num[3][now] == 4)
                {
                    if(tp == 1) getnum(3);
                    else getnum(pos);
                }
                else if(Empty(pos))
                {
                    if(tp == 1) getnum(4);
                    else getnum(pos);
                }
                else if(tmp + num[1][now] > 4)
                {
                    if(tp == 1) getnum(1);
                    else getnum(pos);
                }
            }
            else if(pos == 3)
            {
                int tp = judge3(3);
                if(!tp) {Win = 3;break;}
                while(num[pos][no] > 0)
                {
                    res[N++] = no;
                    num[pos][no]--;
                }
                if(Empty(pos))
                {
                    if(tp == 1) getnum(4);
                    else getnum(pos);
                }
                else if(tmp + num[1][now] > 4)
                {
                    if(tp == 1) getnum(1);
                    else getnum(pos);
                }
            }
            else if(pos == 4)
            {
                tmpb = 0;
                int tp = judge4(4);
                if(!tp) {Win = 4;break;}
                while(num[pos][no] > 0)
                {
                    res[N++] = no;
                    num[pos][no]--;
                }
                if(tmpb) num[pos][nob]--, res[N++] = nob;
                if(!check1(now+1, 1) || tmp + tmpb + num[1][now] > 4)
                {
                    if(tp == 1) getnum(1);
                    else getnum(pos);
                }
                else if(num[3][now] == 4)
                {
                    if(tp == 1) getnum(3);
                    else getnum(pos);
                }
            }
            pos++, now++;
            while(pos > 4) pos -= 4;
            while(now > 13) now -= 13;
        }
        if(!Win)
        for(int i = 1;i <= 4;i++)
        {
            if(Empty(i))
            {
                Win = i;
                break;
            }
        }
        for(int i = 1;i <= 4;i++)
        {
            if(Win == i) printf("WINNER\n");
            else
            {
                bool viss = 0;
                for(int j = 1;j <= 13;j++)
                {
                    for(int k = 0;k < num[i][j];k++)
                    {
                        if(viss) printf(" ");
                        if(str[j-1] == '#') printf("10");
                        else printf("%c", str[j-1]);
                        viss = 1;
                    }
                }
                printf("\n");
            }
        }
    }
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值