1. 程式人生 > >2018 ICPC北京網路賽 C. Cheat (模擬)

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;
}