ACM-ICPC 2018 南京赛区网络预赛 C GDY (暴力模拟)
题目链接:https://nanti.jisuanke.com/t/30992
分析:暴力模拟即可
代码:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
using namespace std;
typedef pair<int,int> pii;
const int N =100000 + 7 , M = 200000 + 7, inf = 0x3f3f3f3f ;
int n,m;
int a[210][20],b[20007],num[210];//a[i][j]为第i个人j牌的数目,b[i]为待取的牌,num[i]为第i个人牌总和
int main(){
FRER();
int T,kase = 1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
mem(a,0);
mem(num,0);
for(int i=1;i<=m;i++) {
scanf("%d",&b[i]);
if(b[i]==1) b[i] = 14;
if(b[i]==2) b[i] = 15;
}
int k = 1;
for(int i=0;i<n;i++){
if(k>m) break;
int cnt = 5;
while(cnt--&&k<=m){
num[i]+=b[k];
a[i][b[k++]]++;
}
}
int cnt = 0 , p = 1 , now , id = 0; // cnt为未出牌的人数,p%n为当前出牌人,now 最后出牌,id为最后出牌人
int j = 3;//第一个人出牌
while(!a[0][j]) j++;
now = j;
a[0][j]--;
num[0]-=j;
while(1){
if(cnt==n-1){//当没人能要的上最后出牌人的牌,摸牌
cnt = 0;
for(int i=id;i<id+n;i++){//摸牌
if(k>m) break;
a[i%n][b[k]]++;
num[i%n]+=b[k++];
}
//最后出牌人出牌
int j = 3;
while(!a[id][j]&&j<=15) j++;
now = j;
num[id]-=j;
a[id][j]--;
if(num[id]==0){
break;
}
p = id + 1;
}else {
int pp = p%n;
//判断是否出牌
if(a[pp][now+1]){
id = pp;
a[pp][now+1]--;
num[pp]-=(now+1);
now = now+1;
if(num[pp]==0){
break;
}
cnt = 0;
}else if(now!=15&&a[pp][15]){
id = pp;
now = 15;
a[pp][15]--;
num[pp]-=15;
if(num[pp]==0){
break;
}
cnt = 0;
}else
cnt++;
p++;
}
}
//由于把1,2转化为14,15,所以最后要减去相应的增加量
for(int i=0;i<n;i++){
if(a[i][14]) num[i]-=13*a[i][14];
if(a[i][15]) num[i]-=13*a[i][15];
}
printf("Case #%d:\n",kase++);
for(int i=0;i<n;i++){
if(!num[i]) printf("Winner\n");
else printf("%d\n",num[i]);
}
}
}