7w523
題目描述
你玩過7王523嗎?
這個撲克牌遊戲可以 2~5 個人玩,最開始的時候,每人 張牌,莊家 張牌。莊家首先出牌,然後輪流出牌或不出牌。
第一個出牌的人可以打出任意牌,後面的人必須比前面的牌大才能出牌,且牌型必須要和前面人出牌的牌型一致或大於前面人的牌型。
牌的大小關係是 7>大王>小王>5>2>3>A>K>Q>J>10>9>8>6>4.不區分花色。
牌型有:對子(兩張牌點數一樣),炸彈(三張牌一樣),氫彈(四張牌一樣)
牌型的大小關係是:氫彈>炸彈>對子、單牌
另外還有一種特殊的出牌規則,如果有人出單牌,某人手上有一樣點數的對子,則有對子的人可以忽略出牌順序直接“碰”。在“碰”後,後面只有炸彈或氫彈可以出。(比如甲出單牌,後面只要有人有碰,一定是先滿足碰)
當某個人打出的牌沒人要時,本輪出牌結束,最後一個出牌的人取得本輪勝利,本輪出的牌就是勝利的人的積分, 張牌記 分。再由勝利的人開始在剩餘牌中按順序拿幾張牌和手上的牌湊夠五張,接下來按順序另外的人也從剩餘牌中按順序拿夠 張。 如果牌庫中牌的數量不夠某個人拿夠張, 則停止拿牌環節。 如果發牌環節結束後某個玩家沒有牌, 則整個遊戲結束, 同時每個玩家的得分加上其手牌數量。
例如:
甲:2 4 4 6 K
乙:3 8 8 J 10
丙:K K 4 A A
剩餘牌:7 7 2
假設出牌順序是甲、乙、丙;
第一輪:甲先出 ,則乙可以出 、 或 ;丙如果不要,則甲可以出 。這個時候沒有人有牌能夠大過 ,該輪出牌結束,甲獲得勝利可以得到 個積分。接下來甲可以從剩餘牌中獲得 個 ,而乙可以獲得 。丙沒有出牌就不能拿。
第二輪:甲出 ,這個時候丙可以跳過乙優先進行“碰”,由於其他人沒有炸彈,所以丙獲得該輪勝利,得到 個積分。
爲了簡化問題,我們不考慮獲勝的策略。也就是說輪到某人出牌,如果他手上的牌有大於前面人出的牌,則他就打出剛好大於前面的牌(有出必出),有“碰”必“碰”。 比如第一個人出 ,第二個人牌是 ,第三個人牌是 ,則第三個人會先碰出來。因爲對於第二個人來說他優先選擇出 ,所以第三個人先碰。
每一輪第一個出牌的人,優先出手中最小的對子(爲了儘可能讓別人要不起,對 7 除外),沒有對子就出最小的單牌,沒有單牌出對 7,沒有對 7 出最小的炸彈,沒有炸彈出氫彈。接下來輪流出牌,出的牌型必須和前面一至或大於前面的牌型,對子、炸彈、氫彈不能拆開出,出牌的原則的剛好大於前面的牌,如果沒有大過前面的牌就 ,由後面一個人出牌。如果一個人出的牌其他人都 ,則本輪結束,最後一個出牌的爲勝利者。
**注:**大王與小王不在一起算單牌,大王和小王在一起算炸彈(不能拆開),且是僅次於 的最大炸彈。任何氫彈都大於任何炸彈, 包括王炸。若牌庫無牌, 且某玩家出牌後剛好打完, 這一回合仍然需要進行完纔算遊戲結束。
開始的時候,第一個人自動作爲莊家先拿前面的 張牌,接下來玩家依次拿 張(若不夠則停止拿牌環節)。當沒有剩餘的牌且發牌環節某個玩家手上沒有牌,遊戲結束,其他玩家手中的沒有打出去的牌自動算爲該玩家的積分。
輸入輸出格式
輸入格式
一共 行;
第一行是一個整數 表示玩家人數,第二行是一個字符串表示初始牌的順序,其中大王用 表示,小王用 表示,10 用 表示。
輸出格式
行,每行是一個整數,表示第 個玩家最後獲得的積分。
輸入輸出樣例
輸入樣例#1:
3
25G36Q3885XKK4AA77A
輸出樣例#1:
13
2
4
樣例解釋
第一輪:第一個人出 6,然後第二個人出 X,第三個人不要,第一個人出 Q,第二個人出 3,第三個人不要,第一個人出 2,第二個人出 5、三個人不要,第一個人出 G,第二三個人不要,第一輪結束。第一個人獲得積分 7,然後獲得 77A 三張牌
第二輪:第一個人出 A, 第三個人有碰優先由第三個人碰,第三個人碰後,沒有人有炸彈,該輪第三個人勝利。第三個人獲得積分 3
第三輪:第三個人出對 K,第一個人出對 7,第一個人取得本輪勝利獲得積分 4 第四輪:第一個人出 3,第二個人、第三個人 pass,第一個人取得勝利獲得積分 1 第五輪:第一個人出 5,第一個人取得勝利獲得積分 1。遊戲結束。最後得分:
第一個人:13
第二個人:2
第三個人:4
【數據特點】
對於 100%數據,保證開始每個人至少有一張牌。一副牌中最多隻有一張大王和小王,每個點數的牌張數不超過 4,所有字母均爲大寫,只有 J,Q,K,A,G,X,F,9,8,7,6,5,4,3,2 這些牌。
測試點 | 玩家人數 | 撲克牌總數 | 特殊情況 |
---|---|---|---|
1 | 2 | 沒有碰、炸彈、氫彈 | |
2 | 2 | 沒有炸彈、氫彈 | |
3 | 3 | ||
4 | 3 | 沒有碰 | |
5 | 3 | 沒有炸彈、氫彈 | |
6 | 4 | 沒有碰 | |
7 | 4 | 沒有王炸 | |
8 | 4 | 沒有碰、炸彈、氫彈 | |
9 | 4 | 沒有炸彈、氫彈 | |
10 | 4 |
題解
辣雞大模擬,不過我大概是全網最短的代碼:
代碼
#include<cstdio>
#include<cstring>
#define put(pos,typ,siz) my[pos][siz]=0,cot[pos]-=typ,flag=1,last=(sd){pos,typ,siz}
const int N=15;
struct sd{int pos,typ,siz;}last;
int val[256],my[6][16],cot[6],sta[55],scr[6],top,n,flag;
char ch[55];
int kind[]={0,'4','6','8','9','X','J','Q','K','A','3','2','5','F','G','7'};
void getcard(int pos,int siz)
{
for(;cot[pos]<siz&⊤++my[pos][sta[top--]],++cot[pos]);
if(my[pos][13]&&my[pos][14])my[pos][13]=0,my[pos][14]=3;
}
void putcard(int pos)
{
int typ=last.typ,siz=last.siz;
if(!typ)
{
for(int i=1;i<N;++i)if(my[pos][i]==2){put(pos,2,i);return;}
for(int i=1;i<=N;++i)if(my[pos][i]==1){put(pos,1,i);return;}
if(my[pos][N]==2){put(pos,2,N);return;}
for(int i=1;i<=N;++i)if(my[pos][i]==3){if(i==14)cot[pos]+=1;put(pos,3,i);return;}
for(int i=1;i<=N;++i)if(my[pos][i]==4){put(pos,4,i);return;}
}
for(int i=1;i<=N;++i)if(my[pos][i]==typ&&i>siz){if(i==14&&typ==3)cot[pos]+=1;put(pos,typ,i);return;}
for(int j=(typ==1?3:typ+1);j<=4;++j)for(int i=1;i<=N;++i)if(my[pos][i]==j){if(i==14&&j==3)cot[pos]+=1;put(pos,j,i);return;}
flag=0;
}
bool peng(){for(int i=0;i<n;++i)if(last.typ==1&&my[i][last.siz]==2)return put(i,2,last.siz),last=(sd){i,3,-1},1;return 0;}
void game()
{
for(int i=1;i<=N;++i)val[kind[i]]=i;
for(int i=strlen(ch+1);i;--i)sta[++top]=val[ch[i]];
getcard(0,6);for(int i=1;i<n;++i)getcard(i,5);
for(int pos,cnt;;last.typ=0,scr[last.pos]+=cnt)
{
for(int i=0;i<n;++i)getcard((last.pos+i)%n,5);
if(!top)for(int i=0;i<n;++i)if(!cot[i])return;
putcard(last.pos),cnt=last.typ;if(last.typ==3&&last.siz==14)cnt-=1;
if(peng())cnt+=2,pos=last.pos;
for(pos=(last.pos+1)%n;pos!=last.pos;pos=(pos+1)%n,flag=0)
{
putcard(pos);
if(flag){cnt+=last.typ;if(last.typ==3&&last.siz==14)cnt-=1;}
if(peng())cnt+=2,pos=last.pos;
}
}
}
void in(){scanf("%d%s",&n,ch+1);}
void ac(){game();for(int i=0;i<n;++i)printf("%d\n",scr[i]+cot[i]);}
int main(){in(),ac();}