| 比赛 |
省选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;
}