传送门
题意:
1)有m张牌放到栈里
2)牌的大小为3<4<5<6<7<8<9<10<11<12<13<1<2
3)n个人,每个人首先每次从栈顶取5张牌。
4)从第1个人出他手里最小的牌,然后按顺序轮流出牌。
5)出牌有两种选择:①出比前一个人的牌大1的牌 ②出2
6)当一个人出了一张2以后,从他开始每个人抽一张牌。
7)如果第i个人没有能出的牌,他就pass。
8)如果第X个人出完牌后除了他之外没有人能出牌,那么从他开始所有人要抽一张牌,然后,X出他手里最小的牌。
9)如果栈里没牌了,那么就跳过取牌的环节
10)谁先出完牌谁胜,剩下的人输出他手中牌的点数和。
思路:模拟。
虽然比赛还是过了,但是还是有一些在模拟中的几个待改进的点:
1)可以建立一个虚拟的0,这样第一个不需要特别判断。
2)这样的顺序可以1,2 变成14,15,避免这之后的判断中出现错误和繁琐的if。
3)记录上一个出牌的人。
4)发牌的时候一张一张发,这张的话所有的发牌操作可以用一个函数来写。
#include<bits/stdc++.h>
#define debug(a) cout << #a << " " << a << endl
#define lnn putchar('\n')
#define see putchar(' ')
#define LL long long
#define ull unsigned long long
#define PI acos(-1.0)
#define eps 1e-6
const int N=2e5+7;
using namespace std;
int a[N];
int f[250][15];
int cnt,n,m;
void init()
{
for(int i=1;i<250;i++)
for(int j=0;j<15;j++) f[i][j]=0;
}
void add(int now)
{
if(cnt>=m) return;
for(int i=1;i<=n;i++){
int nx=now+i-1;
if(nx>n) nx-=n;
f[nx][a[++cnt]]++;
if(cnt==m) break;
}
}
int check(int now)
{
for(int i=1;i<=13;i++){
if(f[now][i]) return 0;
}
return 1;
}
int main ()
{
//yyy_3y
//freopen("1.in","r",stdin);
int T; scanf("%d",&T);
for(int Case=1;Case<=T;Case++){
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
cnt=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=5;j++){
f[i][a[++cnt]]++;
if(cnt==m) break;
}
if(cnt==m) break;
}
int now_person=1;
int pre_card;
for(int i=2;i>=1;i--) if(f[1][i]) pre_card=i;
for(int i=13;i>=3;i--) if(f[1][i]) pre_card=i;
int flag=1;
int ccc=0;
if(pre_card==1) pre_card=13;
else if(pre_card==3) pre_card=-1;
else pre_card--;
while(flag){
if(pre_card==-1){
f[1][3]--;
if(check(now_person)) break;
now_person++;
if(now_person>n) now_person-=n;
pre_card=3;
continue;
}
if(pre_card==2){
add(now_person);
int now_card=-1;
for(int i=2;i>=1;i--) if(f[now_person][i]) now_card=i;
for(int i=13;i>=3;i--) if(f[now_person][i]) now_card=i;
f[now_person][now_card]--;
if(check(now_person)) break;
if(now_card!=2) now_person++;
if(now_person>n) now_person-=n;
pre_card=now_card;
}else{
int now_card=pre_card+1;
if(now_card==14) now_card=1;
if(f[now_person][now_card] && now_card!=2){
f[now_person][now_card]--;
if(check(now_person)) break;
now_person++;
if(now_person>n) now_person-=n;
pre_card=now_card;
ccc=0;
}else if(f[now_person][2]){
f[now_person][2]--;
if(check(now_person)) break;
pre_card=2;
ccc=0;
}else{
ccc++;
now_person++;
if(now_person>n) now_person-=n;
}
if(ccc==n-1){
ccc=0;
add(now_person);
int now_card=-1;
for(int i=2;i>=1;i--) if(f[now_person][i]) now_card=i;
for(int i=13;i>=3;i--) if(f[now_person][i]) now_card=i;
f[now_person][now_card]--;
if(check(now_person)) break;
now_person++;
if(now_person>n) now_person-=n;
pre_card=now_card;
}
}
}
printf("Case #%d:\n",Case);
for(int i=1;i<=n;i++){
int ans=0;
for(int j=1;j<=13;j++){
ans+=f[i][j]*j;
}
if(!ans) puts("Winner");
else printf("%d\n",ans);
}
}
return 0;
}