hiho 1830(2018 北京網路賽 C)
阿新 • • 發佈:2018-12-11
題目連結:點選這裡
解題思路:
play1 : 按相應等級出一張,不能的話只能說謊且出字典序最小的一張.
挑戰1: 陳述者出的rank為X的牌數為p,play1手裡rank為X的牌為q,q+p>4,挑戰陳述者.
挑戰2:下一個陳述者是play1且play1下次陳述必須說謊,挑戰陳述者
paly2:出完手上相應等級的牌,不能的話只能說謊且出字典序最小的一張
挑戰1:下一個陳述者是play2且play2下次陳述必須說謊,挑戰陳述者
play3:出完手上相應等級的牌,不能的話只能說謊且出完手上數量最小的那個rank,如果有多個選擇,選字典序小的那個.
挑戰1::play3手上有4張當前陳述者的rank.挑戰陳述者
play4:如果手上有相應rank的牌3張或者4張,出完該rank牌,不能的話只能說謊且出完相應rank的牌加上一張字典序最小的一張(如果有的話)
挑戰1::當陳述者清空了手上的牌時,挑戰陳述者
#include<bits/stdc++.h> #define fi first #define se second using namespace std; typedef long long ll; const int mx = 1e3+10; const int a[] = {9,1,2,3,4,5,6,7,8,0,10,12,11};//字典序 int n,m,rem[20]; int cnt[6][20]; char str[10]; int Get(){ if(str[0] == 'A')return 0; if(str[0] == 'J')return 10; if(str[0] == 'Q')return 11; if(str[0] == 'K')return 12; if(str[0] == '1')return 9; return (int)(str[0]-'0'-1); } void input(int x){ if(x==0) putchar('A'); else if(x>=1&&x<=8) putchar(x+'0'+1); else if(x==9) printf("10"); else if(x==10) putchar('J'); else if(x==11) putchar('Q'); else putchar('K'); putchar(' '); } bool cut(int H)//減去一張字典序最小的牌 { for(int i=0;i<13;i++) if(cnt[H][a[i]]){ cnt[H][a[i]]--; rem[a[i]]++; return 1; } return 0; } pair<int,int> down(int H,int beg,int v1) { if(cnt[H][beg]){ if(v1){ cnt[H][beg]--,rem[beg]++; return make_pair(1,1); }else{ rem[beg] += cnt[H][beg]; int v = cnt[H][beg]; cnt[H][beg] = 0; return make_pair(1,v); } }else{ cut(H); return make_pair(0,1); } } pair<int,int> Put(int H,int beg)//相應的出牌規則 { if(H<2) return down(H,beg,H^1); else if(H==2){ if(cnt[H][beg]){ rem[beg] += cnt[H][beg]; int v = cnt[H][beg]; cnt[H][beg] = 0; return make_pair(1,v); }else{ int mi = 100,p; for(int i=0;i<13;i++) if(cnt[H][a[i]]&&mi>cnt[H][a[i]]) mi = cnt[H][a[i]],p = a[i]; rem[p] += cnt[H][p]; int v = cnt[H][p]; return make_pair(cnt[H][p] = 0,v); } }else{ rem[beg] += cnt[H][beg]; int v = cnt[H][beg]; cnt[H][beg] = 0; if(v<3&&cut(H)) return make_pair(0,v+1); return make_pair(1,v); } } bool empty(int H) { for(int i=0;i<13;i++) if(cnt[H][i]) return 0; return 1; } bool check(int x,int H,int beg,int v)//是否挑戰 { if(x==0){ if(v+cnt[x][beg]>4) return 1; if((H+1)%4==x&&cnt[x][(beg+1)%13]==0) return 1; }else if(x==1){ if((H+1)%4==x&&cnt[x][(beg+1)%13]==0) return 1; }else if(x==2){ if(cnt[x][beg]==4) return 1; }else{ if(empty(H)) return 1; } return 0; } int solve() { int H = 0,beg = 0; while(1){ pair<int,int> pa = Put(H,beg); for(int i=0;i<4;i++) if(i!=H&&check(i,H,beg,pa.se)){ int g = pa.fi? i:H;//收回桌上的牌 for(int j=0;j<13;j++) cnt[g][j] += rem[j],rem[j] = 0; break; } if(empty(H)) return H; H = (H+1)%4,beg = (beg+1)%13; } } int main() { while(~scanf("%s",str)) { memset(cnt,0,sizeof(cnt)); memset(rem,0,sizeof(rem)); cnt[0][Get()]++; for(int i=0;i<12;i++){ scanf("%s",str); cnt[0][Get()]++; } for(int i=1;i<=3;i++){ for(int j=1;j<=13;j++){ scanf("%s",str); cnt[i][Get()]++; } } int ans = solve(); for(int i=0;i<4;i++){ if(ans==i) puts("WINNER"); else{ for(int j=0;j<13;j++) while(cnt[i][j]--) input(j); puts(""); } } } return 0; }