2018 ICPC北京網路賽 C. Cheat (模擬)
阿新 • • 發佈:2018-11-10
噁心的大模擬……
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; }