1 solutions

  • 0
    @ 2023-12-3 21:35:15

    C++ :

    #pragma GCC optimize(3)
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    const int maxn = 110;
    const int maxk = 210;
    const int maxr = 1010;
    const long double eps = 1e-8;
    
    int n, m, k, R, h;
    
    int map[maxn][maxn];
    
    int x[maxk], y[maxk];
    
    int a[maxk], b[maxk], c[maxk], d[maxk];
    
    int f[maxk], z[maxk], r[maxk], s[maxk];
    
    int v[maxk], o[maxk], l[maxk];
    
    int nown[maxk], nowm[maxk], skillable[maxk], bombed[maxk], dead[maxk];
    
    int id[maxk];
    
    int history[maxr][maxk][9];
    
    int dx[4], dy[4];
    
    int q[2][maxk];
    
    int lastp;
    
    int result[maxk];
    
    bool use[maxk];
    
    long double fac[1000010];
    
    queue<int> enforce[maxk];
    
    int get_num_of_skill(string s) {
        if (s == "toolihai")
            return 1;
        if (s == "faceking")
            return 2;
        if (s == "onepunch")
            return 3;
        if (s == "rabiribi")
            return 4;
        if (s == "firework")
            return 5;
        if (s == "viuganda")
            return 6;
        if (s == "2dsaigao")
            return 7;
        if (s == "gugugugu")
            return 8;
        if (s == "backward")
            return 9;
        if (s == "hupraise")
            return 10;
        return -100;
    }
    
    int sign(long double l) {
        if (fabsl(l) <= eps)
            return 0;
        if (l < 0)
            return -1;
        else
            return 1;
    }
    
    int dis(int i, int j) { return abs(x[i] - x[j]) + abs(y[i] - y[j]); }
    
    void init_one(int i) {
        nown[i] = a[i];
        nowm[i] = b[i];
        skillable[i] = 0;
        bombed[i] = 0;
        while (enforce[i].size()) enforce[i].pop();
        dead[i] = 0;
    }
    
    void init() {
        scanf("%d%d%d%d", &n, &m, &k, &R);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) scanf("%d", &map[i][j]);
        for (int i = 1; i <= k; i++) {
            scanf("%d%d", &x[i], &y[i]);
            scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
            scanf("%d%d", &f[i], &z[i]);
            scanf("%d", &r[i]);
    
            string name;
            cin >> name;
            s[i] = get_num_of_skill(name);
    
            if (s[i] == 1) {
            } else if (s[i] == 2) {
            } else if (s[i] == 3) {
                scanf("%d%d", &v[i], &l[i]);
            } else if (s[i] == 4) {
                scanf("%d", &v[i]);
            } else if (s[i] == 5) {
                scanf("%d", &l[i]);
            } else if (s[i] == 6) {
            } else if (s[i] == 7) {
                scanf("%d%d%d", &o[i], &v[i], &l[i]);
            } else if (s[i] == 8) {
            } else if (s[i] == 9) {
                scanf("%d", &l[i]);
            } else if (s[i] == 10) {
            } else {
                // fprintf(stderr,"wang yu zhong tian xia wu di, yang jing qin ye ye sheng hui.\n");
            }
    
            init_one(i);
        }
    
        for (int i = 0; i <= n + 1; i++) map[i][0] = map[i][m + 1] = 1;
        for (int i = 0; i <= m + 1; i++) map[0][i] = map[n + 1][i] = 1;
    
        lastp = 0;
    }
    
    void respawn(int i) {
        // fprintf(stderr,"%d respawns\n",i);
        init_one(i);
    }
    
    void recover() {
        // fprintf(stderr,"recover begin\n");
        for (int i = 1; i <= k; i++) {
            if (dead[i] > 0) {
                dead[i]--;
                if (!dead[i])
                    respawn(i);
            }
            if (f[i] > 0)
                f[i]--;
            if (skillable[i] > 0)
                skillable[i]--;
            if (bombed[i] > 0)
                bombed[i]--;
            while (enforce[i].size() > 0) {
                int fv = enforce[i].front();
                if (fv == h) {
                    enforce[i].pop();
                    nown[i] = max(nown[i] - v[i], 0);
                    nowm[i] = min(nowm[i], max(nown[i] - v[i], 0));
                    // fprintf(stderr,"%d enforce disappears, back to (%d,%d)\n",i,nown[i],nowm[i]);
                } else
                    break;
            }
        }
    }
    
    void log() {
        for (int i = 1; i <= k; i++) {
            history[h][i][0] = h;
            history[h][i][1] = x[i];
            history[h][i][2] = y[i];
            history[h][i][3] = d[i];
            history[h][i][4] = nown[i];
            history[h][i][5] = nowm[i];
            history[h][i][6] = dead[i];
            history[h][i][7] = bombed[i];
            history[h][i][8] = skillable[i];
        }
    }
    
    void move() {
        // fprintf(stderr,"move begins\n");
        for (int i = 1; i <= k; i++)
            if (!bombed[i] && !dead[i]) {
                int xx = x[i] + dx[d[i]];
                int yy = y[i] + dy[d[i]];
                if (map[xx][yy]) {
                    d[i] = d[i] ^ 1;
                    // fprintf(stderr,"%d turns at (%d,%d)\n",i,x[i],y[i]);
                } else {
                    // fprintf(stderr,"%d moves from (%d,%d) to (%d,%d)\n",i,x[i],y[i],xx,yy);
                    x[i] = xx;
                    y[i] = yy;
                }
            }
    }
    
    bool dfs(int now) {
        for (int i = 1; i <= k; i++)
            if (c[i] && ((nown[i] ^ nown[now]) % 3 == 0) && !use[i]) {
                use[i] = true;
                if (!result[i] || dfs(result[i])) {
                    result[i] = now;
                    return true;
                }
            }
        return false;
    }
    
    void matching() {
        int ans = 0;
        memset(result, 0, sizeof(result));
        for (int i = 1; i <= k; i++)
            if (!c[i]) {
                memset(use, false, sizeof(use));
                if (dfs(i))
                    ans++;
            }
        printf("%d\n", ans);
    }
    
    bool check_in(int j, int i) {
        int ndx = x[j] - x[i];
        int ndy = y[j] - y[i];
        if (d[i] == 0)
            ndx = -ndx;
        else if (d[i] == 2) {
            ndy = -ndy;
            swap(ndx, ndy);
        } else
            swap(ndx, ndy);
        return ndx >= 1 && ndx <= v[i] && ndy >= -ndx && ndy <= ndx;
    }
    
    void skill() {
        // fprintf(stderr,"skill begin\n");
        bool skip[2] = { false, false };
        for (int i = 1; i <= k; i++)
            if (!f[i] && !skillable[i] && !skip[c[i]] && !dead[i]) {
                // fprintf(stderr,"%d use skills %d\n",i,s[i]);
                f[i] = z[i];
                if (s[i] == 1) {
                    lastp = i;
                } else if (s[i] == 2) {
                    for (int j = 1; j <= k; j++)
                        if (!dead[j]) {
                            if (d[j] == 0)
                                d[j] = 2;
                            else if (d[j] == 1)
                                d[j] = 3;
                            else if (d[j] == 2)
                                d[j] = 1;
                            else
                                d[j] = 0;
                        }
                } else if (s[i] == 3) {
                    enforce[i].push(h + l[i]);
                    nown[i] += v[i];
                    // fprintf(stderr,"enforce to (%d,%d)\n",nown[i],nowm[i]);
                } else if (s[i] == 4) {
                    for (int j = 1; j <= k; j++)
                        if (check_in(j, i)) {
                            // fprintf(stderr,"%d is knoced from (%d,%d) to",j,x[j],y[j]);
                            x[j] += dx[d[i]];
                            y[j] += dy[d[i]];
                            while (map[x[j]][y[j]]) {
                                if (!x[j])
                                    x[j] = n;
                                else if (x[j] == n + 1)
                                    x[j] = 1;
                                else if (!y[j])
                                    y[j] = m;
                                else if (y[j] == m + 1)
                                    y[j] = 1;
                                else {
                                    x[j] += dx[d[i]];
                                    y[j] += dy[d[i]];
                                }
                            }
                            // fprintf(stderr," (%d,%d)\n",x[j],y[j]);
                        }
                } else if (s[i] == 5) {
                    if (lastp)
                        bombed[lastp] += l[i];
                    else
                        bombed[i] += l[i];
                } else if (s[i] == 6) {
                    int maxp = 0, minp = 0;
                    for (int j = 1; j <= k; j++)
                        if (dead[j]) {
                            int distance = dis(i, j);
                            if (c[i] == c[j]) {
                                if (!maxp || distance >= dis(maxp, i))
                                    maxp = j;
                            } else {
                                if (!minp || distance <= dis(minp, i))
                                    minp = j;
                            }
                        }
                    if (maxp)
                        respawn(maxp);
                    else if (minp)
                        respawn(minp);
                } else if (s[i] == 7) {
                    int nx = x[i];
                    int ny = y[i];
                    int ndx = dx[d[i]], ndy = dy[d[i]];
                    if (d[i] == 0)
                        ndy = 1;
                    else if (d[i] == 1)
                        ndy = -1;
                    else if (d[i] == 2)
                        ndx = -1;
                    else
                        ndx = 1;
                    for (int j = 1; j <= o[i]; j++) {
                        int nnx = nx + ndx;
                        int nny = ny + ndy;
                        if (map[nnx][nny]) {
                            ndx = ndy;
                            ndy = -ndx;
                            nnx = nnx + ndx;
                            nny = nny + ndy;
                            nnx = (nnx + nx) / 2;
                            nny = (nny + ny) / 2;
                            if (map[nnx][nny]) {
                                ndx = ndy;
                                ndy = -ndx;
                            } else {
                                nx = nnx;
                                ny = nny;
                            }
                        } else {
                            nx = nnx;
                            ny = nny;
                        }
                    }
                    x[0] = nx;
                    y[0] = ny;
                    // fprintf(stderr,"bomed at (%d,%d)\n",x[0],y[0]);
                    for (int j = 1; j <= k; j++)
                        if (dis(0, j) <= v[i]) {
                            skillable[j] += l[i];
                            // fprintf(stderr,"effect %d\n",j);
                        }
                } else if (s[i] == 8) {
                    skip[c[i]] = true;
                } else if (s[i] == 9) {
                    int j = h - l[i];
                    x[i] = history[j][i][1];
                    y[i] = history[j][i][2];
                    d[i] = history[j][i][3];
                    nown[i] = history[j][i][4];
                    nowm[i] = history[j][i][5];
                    dead[i] = history[j][i][6];
                    bombed[i] = history[j][i][7];
                    skillable[i] = history[j][i][8];
                    // fprintf(stderr,"%d jumps back to %d\n",i,j);
                } else if (s[i] == 10) {
                    // fprintf(stderr,"matching begins\n");
                    matching();
                } else {
                    printf("wang yu zhong tian xia wu di, yang jing qin ye ye sheng hui.\n");
                }
            }
    }
    
    bool cmp(int i, int j) {
        if (x[i] == x[j])
            return y[i] < y[j];
        else
            return x[i] < x[j];
    }
    
    void change(int i, int j) {
        nown[j] = max(nown[j] - nown[i], 0);
        nowm[j] = max(nowm[j] - nown[i], 0);
    }
    
    void die(int i) { dead[i] = r[i]; }
    
    long double combinational(int i) { return fac[nown[i]] - fac[nowm[i]] - fac[nown[i] - nowm[i]]; }
    
    bool cmp2(int i, int j) { return sign(combinational(i) - combinational(j)) < 0; }
    
    void fight() {
        // fprintf(stderr,"fight begins\n");
        for (int i = 1; i <= k; i++) id[i] = i;
        sort(id + 1, id + k + 1, cmp);
        for (int i = 1; i <= k;) {
            int j = i;
            while (j <= k && x[id[j]] == x[id[i]] && y[id[j]] == y[id[i]]) j++;
            bool exists[2] = { false, false };
            for (int t = i; t < j; t++)
                if (!dead[id[t]])
                    exists[c[id[t]]] = true;
            if (exists[0] && exists[1]) {
                int cnt[2] = { 0, 0 };
                for (int t = i; t < j; t++)
                    if (!dead[id[t]]) {
                        cnt[c[id[t]]]++;
                        q[c[id[t]]][cnt[c[id[t]]]] = id[t];
                    }
                sort(q[0] + 1, q[0] + cnt[0] + 1, cmp2);
                sort(q[1] + 1, q[1] + cnt[1] + 1, cmp2);
                // fprintf(stderr,"One fight begins\n");
                // fprintf(stderr,"Team 0");
                // for (int t=1;t<=cnt[0];t++)
                // fprintf(stderr," %d",q[0][t]);
                // fprintf(stderr,"\n");
                // fprintf(stderr,"Team 1");
                // for (int t=1;t<=cnt[1];t++)
                // fprintf(stderr," %d",q[1][t]);
                // fprintf(stderr,"\n");
                int p1 = cnt[0], p2 = cnt[1];
                while (p1 != 0 && p2 != 0) {
                    int id1 = q[0][p1];
                    int id2 = q[1][p2];
                    if (cmp2(id1, id2)) {
                        p1--;
                        change(id1, id2);
                        die(id1);
                    } else {
                        if (cmp2(id2, id1)) {
                            p2--;
                            change(id2, id1);
                            die(id2);
                        } else {
                            p1--;
                            p2--;
                            die(id2);
                            die(id1);
                        }
                    }
                }
                // fprintf(stderr,"fight res %d %d\n",p1,p2);
            }
            i = j;
        }
    }
    
    void gg_check() {
        for (int i = 1; i <= k; i++)
            if (x[i] < 1 || x[i] > n || y[i] < 1 || y[i] > m) {
                printf("%d\n", h);
                exit(0);
            }
    }
    
    void simulate() {
        for (int now_round = 1; now_round <= R; now_round++) {
            // fprintf(stderr,"%d ronud begins\n",now_round);
            h = now_round;
    
            recover();
            log();
            move();
            skill();
            fight();
            // gg_check();
        }
        for (int i = 1; i <= k; i++) printf("%d %d\n", x[i], y[i]);
    }
    
    int main() {
        // freopen("1.in","r",stdin);
        // freopen("1.out","w",stdout);
        dx[0] = -1;
        dx[1] = 1;
        dy[2] = -1;
        dy[3] = 1;
        for (int a = 1; a <= 1000000; a++) fac[a] = fac[a - 1] + logl(a);
        int T;
        scanf("%d", &T);
        for (int test = 1; test <= T; test++) {
            // printf("%d\n",test);
            // fprintf(stderr,"%d game begins\n",test);
            init();
            simulate();
            // fprintf(stderr,"\n\n");
        }
    
        return 0;
    }
    
    • 1

    Information

    ID
    1312
    Time
    10000ms
    Memory
    512MiB
    Difficulty
    (None)
    Tags
    # Submissions
    0
    Accepted
    0
    Uploaded By