恶心的大模拟……
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;
}