比赛 省选2023Day2复现 评测结果 AAAAAAAAATTTTTAATATT
题目名称 过河卒 最终得分 60
用户昵称 flyfree 运行时间 15.267 s
代码语言 C++ 内存使用 192.99 MiB
提交时间 2025-12-13 11:17:27
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
// #define LOCAL
#define ll long long
#define db double
#define Ciallo true
#define pir pair <ll,ll>
#define fs first
#define sc second
#define MAXN 2000010
inline ll read(){
    ll f = 1, num = 0;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c=='-') f = -1;c = getchar();
    }
    while(c>='0'&&c<='9') num = num * 10 + c - '0', c = getchar();
    return num * f;
}

ll fp[10];
// S 1e6 位 = 0/1 表示黑方还是红方移动,1e5~4 位表示黑方位置,剩下表示红方位置
vector <int> e0[MAXN],e1[MAXN],e2[MAXN];// 正边,反边,层间边
int deg[MAXN];
int get(int S, int pos){
    return (S / fp[pos]) % 10;
}
int f[MAXN],g[MAXN];// 当前状态是2必胜/1必败/0不确定(必和),到游戏结束有多少步
int n,m;
int adx[4] = {0, -1, 0, 1};
int ady[4] = {-1, 0, 1, 0};
char c[12][12];
vector <int> vec[12];
bool ins[MAXN];

int has(int flag, int bx, int by, int rx1, int ry1, int rx2, int ry2){
    if(rx2 < rx1 || (rx2 == rx1 && ry2 < ry1))swap(rx1, rx2), swap(ry1, ry2);
    return flag * fp[6] + bx * fp[5] + by * fp[4] + rx1 * fp[3] + ry1 * fp[2] + rx2 * fp[1] + ry2;
}

int stbx, stby, strx1, stry1, strx2, stry2;
bool getr1;
vector <int> vecP;
bool vis[MAXN];

void clearall(){
    getr1 = false;
    stbx = stby = strx1 = stry1 = strx2 = stry2 = 0;
    for(int i = 1;i <= 10; ++i)vec[i].clear();
    for(int S = 0;S <= 2e6; ++ S){
        f[S] = g[S] = 0;
        ins[S] = false;
        e0[S].clear(), e1[S].clear(), e2[S].clear();
        deg[S] = 0;
        vis[S] = 0;
    }
}

void bfs(int st){
    auto chk = [&](int S){
        int bx = get(S, 5), by = get(S, 4);
        int rx1 = get(S, 3), ry1 = get(S, 2);
        int rx2 = get(S, 1), ry2 = get(S, 0);
        if(c[bx][by] == '#' || c[rx1][ry1] == '#' || c[rx2][ry2] == '#')return false;
        if(bx >= n || rx1 >= n || rx2 >= n)return false;
        if(by >= m || ry1 >= m || ry2 >= m)return false;
        if(rx1 == rx2 && ry1 == ry2)return false;
        if(rx2 < rx1 || (rx2 == rx1 && ry2 < ry1))return false;
        return Ciallo;
    };

    auto chkdd = [&](int S){
        int bx = get(S, 5), by = get(S, 4);
        int rx1 = get(S, 3), ry1 = get(S, 2);
        int rx2 = get(S, 1), ry2 = get(S, 0);
        if(bx == rx1 && by == ry1)return Ciallo;
        if(bx == rx2 && by == ry2)return Ciallo;
        return false;
    };

    queue <int> q;
    q.push(st);
    vis[st] = Ciallo;
    vecP.push_back(st);
    while(!q.empty()){
        int S = q.front();
        q.pop();
        int bx = get(S, 5), by = get(S, 4);
        int rx1 = get(S, 3), ry1 = get(S, 2);
        int rx2 = get(S, 1), ry2 = get(S, 0);
        int flag = get(S, 6);
        vec[bx].push_back(S);

        if(bx == 0){
            if(flag)f[S] = 1, g[S] = 0;
            else f[S] = 2, g[S] = 0;
            continue;
        }
        if(chkdd(S)){
            f[S] = 1, g[S] = 0;
            continue;
        }

        if(!flag){// 黑棋走
            for(int i = 0;i < 3; ++i){
                int nx = bx + adx[i], ny = by + ady[i];
                if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
                int ns = has(flag ^ 1, nx, ny, rx1, ry1, rx2, ry2);
                if(!chk(ns))continue;
                if(nx != bx){
                    e2[S].push_back(ns);
                }else{
                    e0[S].push_back(ns), e1[ns].push_back(S);
                    ++ deg[S];
                }
            }
        }else{
            // 走第一个红棋
            for(int i = 0;i < 4; ++i){
                int nx = rx1 + adx[i], ny = ry1 + ady[i];
                if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
                int ns = has(flag ^ 1, bx, by, nx, ny, rx2, ry2);
                if(!chk(ns))continue;
                e0[S].push_back(ns), e1[ns].push_back(S);
                ++ deg[S];
            }

            // 走第二个红棋
            for(int i = 0;i < 4; ++i){
                int nx = rx2 + adx[i], ny = ry2 + ady[i];
                if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
                int ns = has(flag ^ 1, bx, by, rx1, ry1, nx, ny);
                if(!chk(ns))continue;
                e0[S].push_back(ns), e1[ns].push_back(S);
                ++ deg[S];
            }
        }

        for(auto T : e0[S]){
            if(!vis[T]){
                q.push(T);
                vis[T] = Ciallo;
            }
        }
        for(auto T : e2[S]){
            if(!vis[T]){
                q.push(T);
                vis[T] = Ciallo;
            }
        }
    }
}

void work(){
    clearall();
    cin >> n >> m;
    // cerr << n << " " << m << endl;
    for(int i = 0;i < n; ++i){
        for(int j = 0;j < m; ++j){
            cin >> c[i][j];
            if(c[i][j] == 'X')stbx = i, stby = j;
            if(c[i][j] == 'O'){
                if(!getr1)strx1 = i, stry1 = j, getr1 = Ciallo;
                else strx2 = i, stry2 = j;     
            }
        }
    }
    
    int ST = has(1, stbx, stby, strx1, stry1, strx2, stry2);
    bfs(ST);
    cerr << ST << endl;

    // auto chk = [&](int S){
    //     int bx = get(S, 5), by = get(S, 4);
    //     int rx1 = get(S, 3), ry1 = get(S, 2);
    //     int rx2 = get(S, 1), ry2 = get(S, 0);
    //     if(c[bx][by] == '#' || c[rx1][ry1] == '#' || c[rx2][ry2] == '#')return false;
    //     if(bx >= n || rx1 >= n || rx2 >= n)return false;
    //     if(by >= m || ry1 >= m || ry2 >= m)return false;
    //     if(rx1 == rx2 && ry1 == ry2)return false;
    //     if(rx2 < rx1 || (rx2 == rx1 && ry2 < ry1))return false;
    //     return Ciallo;
    // };

    // auto chkdd = [&](int S){
    //     int bx = get(S, 5), by = get(S, 4);
    //     int rx1 = get(S, 3), ry1 = get(S, 2);
    //     int rx2 = get(S, 1), ry2 = get(S, 0);
    //     if(bx == rx1 && by == ry1)return Ciallo;
    //     if(bx == rx2 && by == ry2)return Ciallo;
    //     return false;
    // };

    // for(int S = 0;S < 2e6; ++S){
    //     if(!chk(S))continue;
    //     // cerr << S << endl;
    //     int bx = get(S, 5), by = get(S, 4);
    //     int rx1 = get(S, 3), ry1 = get(S, 2);
    //     int rx2 = get(S, 1), ry2 = get(S, 0);
    //     int flag = get(S, 6);
    //     vec[bx].push_back(S);

    //     if(bx == 0){
    //         if(flag)f[S] = 1, g[S] = 0;
    //         else f[S] = 2, g[S] = 0;
    //         continue;
    //     }
    //     if(chkdd(S)){
    //         f[S] = 1, g[S] = 0;
    //         continue;
    //     }

    //     if(!flag){// 黑棋走
    //         for(int i = 0;i < 3; ++i){
    //             int nx = bx + adx[i], ny = by + ady[i];
    //             if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
    //             int ns = has(flag ^ 1, nx, ny, rx1, ry1, rx2, ry2);
    //             if(!chk(ns))continue;
    //             if(nx != bx){
    //                 e2[S].push_back(ns);
    //             }else{
    //                 e0[S].push_back(ns), e1[ns].push_back(S);
    //                 ++ deg[S];
    //             }
    //         }
    //     }else{
    //         // 走第一个红棋
    //         for(int i = 0;i < 4; ++i){
    //             int nx = rx1 + adx[i], ny = ry1 + ady[i];
    //             if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
    //             int ns = has(flag ^ 1, bx, by, nx, ny, rx2, ry2);
    //             if(!chk(ns))continue;
    //             e0[S].push_back(ns), e1[ns].push_back(S);
    //             ++ deg[S];
    //         }

    //         // 走第二个红棋
    //         for(int i = 0;i < 4; ++i){
    //             int nx = rx2 + adx[i], ny = ry2 + ady[i];
    //             if(nx < 0 || ny < 0 || nx >= n || ny >= m || c[nx][ny] == '#')continue;
    //             int ns = has(flag ^ 1, bx, by, rx1, ry1, nx, ny);
    //             if(!chk(ns))continue;
    //             e0[S].push_back(ns), e1[ns].push_back(S);
    //             ++ deg[S];
    //         }
    //     }

    //     // if(!e0[S].size() && !e2[S].size()){
    //     //     f[S] = 1;
    //     //     g[S] = 0;
    //     // }
    //     // cerr << S << " " << deg[S] << endl;
    // }

    auto update = [&](int S, int T){// 用 T 更新一次 S
        if(f[T] == 1){
            if(f[S] != 2){
                f[S] = 2;
                g[S] = g[T] + 1;
            }else{
                g[S] = min(g[S], g[T] + 1);
            }
        }else if(f[T] == 2){
            if(f[S] == 2)return;
            g[S] = max(g[S], g[T] + 1);
        }
    };

    for(int h = 1;h < n; ++h){
        // cerr << h << endl;
        for(auto S : vec[h]){
            for(auto T : e2[S]){
                update(S, T);
                if(f[T] == 0)++ deg[S];// 如果 T 可以平局,那么 S 一定可以守和,在这一层中不能被入队
            }

            if(!deg[S] && !f[S]){
                f[S] = 1;
            }

            if(f[S] == 1){
                for(auto T : e1[S])update(T, S);
            }
        }

        {// 先拓展黑点必胜的情况
            vector <int> beg;
            for(auto S : vec[h]){
                int flag = get(S, 6);
                if(flag)continue;
                if(f[S] == 2){
                    beg.push_back(S);
                    // ins[S] = Ciallo;
                }
            }

            sort(beg.begin(), beg.end(), [&](int id1, int id2){
                return g[id1] < g[id2];
            });
            
            priority_queue <pir, vector <pir>, greater <pir> > q;
            for(auto y : beg)q.push({g[y], y});
            while(!q.empty()){
                int now = q.top().sc;
                q.pop();
                if(ins[now])continue;
                ins[now] = Ciallo;
                int flag = get(now, 6);
                for(auto y : e1[now]){
                    update(y, now);
                    if(flag){// 当前点是红点必败
                        q.push({g[y], y});
                    }else{// 当前点是黑点必胜
                        -- deg[y];
                        if(!deg[y] && !f[y]){
                            f[y] = 1;
                            q.push({g[y], y});
                        }
                    }
                }
            }   
        }

        {// 拓展红点必胜的情况
            vector <int> beg;
            for(auto S : vec[h]){
                int flag = get(S, 6);
                if(!flag)continue;
                if(f[S] == 2){
                    beg.push_back(S);
                    // ins[S] = Ciallo;
                }
            }

            sort(beg.begin(), beg.end(), [&](int id1, int id2){
                return g[id1] < g[id2];
            });
            
            priority_queue <pir, vector <pir>, greater <pir> > q;
            for(auto y : beg)q.push({g[y], y});

            while(!q.empty()){
                int now = q.top().sc;
                q.pop();
                if(ins[now])continue;
                ins[now] = Ciallo;
                int flag = get(now, 6);
                for(auto y : e1[now]){
                    update(y, now);
                    if(!flag){// 当前点是黑点必败
                        q.push({g[y], y});
                    }else{// 当前点是红点必胜
                        -- deg[y];
                        if(!deg[y] && !f[y]){
                            f[y] = 1;
                            q.push({g[y], y});
                        }
                    }
                }
            }
        }
    }

    // for(int i = 1;i < 2e6; ++i){
    //     if(!chk(i) || (!f[i] && !g[i]))continue;
    //     cout << i << " " <<  f[i] << " " << g[i] << endl;
    //     // cout << i + 1000000 << " " << f[i + 1000000] << " " << g[i + 1000000] << endl;
    // }

    // cerr << 
    // int ss = 1724260;
    // cerr << c[1][8] << endl;
    // cerr << ss << " " << f[ss] << " " << g[ss] << " " << chk(ss) << endl;

    if(f[ST] == 2){
        cout << "Red " << g[ST] << endl;
    }else if(f[ST] == 1){
        cout << "Black " << g[ST] << endl;
    }else{
        cout << "Tie\n";
    }
}

int main(int argc, char* argv[]){
    freopen("zu.in", "r", stdin);
    freopen("zu.out", "w", stdout);
    #ifdef FS
        freopen(argv[1], "r", stdin);
        freopen(argv[2], "w", stdout);
    #elif defined(LOCAL)
        freopen("w.in", "r", stdin);
        freopen("w.out", "w", stdout);
    #endif

    fp[0] = 1;
    for(int i = 1;i <= 6; ++i)fp[i] = fp[i - 1] * 10;
    int type = read(), t = read();
    while(t --)work();

    cerr << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << "s \n";
    return 0;
}