1. 程式人生 > >ACM-ICPC 2018 南京賽區網路預賽 C GDY (暴力模擬)

ACM-ICPC 2018 南京賽區網路預賽 C GDY (暴力模擬)

分析:暴力模擬即可

程式碼:

#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]);
        }
    }
}