rt,手推的不知道对不对
代码略长。
常数肯定大,但是现在连正确都做不到就先不管了。
悬1关注找错,若您愿意帮调再加1关。
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define Inf (int)IFINITY
#define inf 0x3f3f3f3f3f
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define unordered_map __gnu_pbds::gp_hash_table//好习惯
#define pb push_back
using namespace std;
inline void read(int &x){
x=0;bool f=0;char c=getchar();
while(c>'9'||c<'0'){f=c=='-';c=getchar();}
while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
if(f) x=-x;
// cin>>x;
}
#define cin(x) read(x)
const int M=15;
const int N=1e7+10;
const int fx[]={0,1,0,-1};
const int fy[]={1,0,-1,0};
struct zt{//存状态
bool f;//0红1黑在走
int r1x,r1y,r2x,r2y,bx,by;
void build(bool F,int R1x,int R1y,int R2x,int R2y,int Bx,int By){
f=F;
r1x=R1x;r1y=R1y;
r2x=R2x;r2y=R2y;
bx=Bx;by=By;
}
bool out(){//黑棋走到第一行
return bx==1;
}
bool eat(){//红黑存在重叠
return (r1x==bx&&r1y==by)||
(r2x==bx&&r2y==by);
}
bool operator==(const zt&y)const{//判相等,unmap要用
return f==y.f&&
r1x==y.r1x&&r1y==y.r1y&&
r2x==y.r2x&&r2y==y.r2y&&
bx==y.bx&&by==y.by;
}
};
struct myhash{//自定义哈希函数,不清楚是不是这里的问题
static uint64_t splitmix64(uint64_t x){
x+=0x9e3779b97f4a7c15;
x=(x^(x>>30))*0xbf58476d1ce4e5b9ll;
x=(x^(x>>27))*0x94d049bb133111ebll;
return x^(x>>31);
}
size_t operator()(uint64_t x)const{
static const uint64_t FIXED_RANDOM=chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x+FIXED_RANDOM);
}
size_t operator()(zt x)const{
static const uint64_t FIXED_RANDOM=chrono::steady_clock::now().time_since_epoch().count();
return (splitmix64(x.bx+FIXED_RANDOM)^(splitmix64(x.by+FIXED_RANDOM)>>1)<<1)^
(splitmix64(x.r1x+FIXED_RANDOM)^(splitmix64(x.r1y+FIXED_RANDOM)>>1)<<1)^
(splitmix64(x.r2x+FIXED_RANDOM)^(splitmix64(x.r2y+FIXED_RANDOM)>>1)<<1);
}
};
zt st;//初始状态
unordered_map<char,int> val;//字符转数字
unordered_map<zt,int,myhash> f;//对状态进行编号
int id,T,n,m,cnt;//cnt表示状态编号总数
int a[M][M];//地图
int dp[N],win[N],in[N];//dp就是状态所需步数,win是胜负(0当前先手输/平局,1当前先手赢),in是入度
bool flg=0;
int get(int x,int y){//坐标转数字
return (x-1)*m+y;
}
pii _get(int x){//数字转坐标
int y=x%m;
x-=y;
x=x/m+1;
return {x,y};
}
vector<int> nxt[N];//建图
deque<int> q;//拓扑的队列
void dfs(zt x){//dfs求能到达的状态
if(f[x]) return;
f[x]=++cnt;//编号
#ifdef debug
cout<<cnt<<endl;
#endif
if(x.f==1){
if(x.eat()){//有吃子的结束状态
q.pb(f[x]);//加入队列
return;
}
bool flg=0;
for(int i=0;i<3;i++){//不能往下走
zt y=x;
y.f^=1;
y.bx+=fx[i],y.by+=fy[i];
if(y.bx<=0||y.bx>n||y.by<=0||y.by>m||a[y.bx][y.by]==-1) continue;//出界或者障碍
else{
flg=1;//标记黑方能走
dfs(y);
nxt[f[y]].pb(f[x]);//反向建图
in[f[x]]++;
}
}
if(!flg){//黑方不能走就输了,红赢
q.pb(f[x]);
return;
}
}
else{
if(x.out()||x.eat()){//现在是红方走,那黑方到第一行或者有吃子就是黑赢
q.pb(f[x]);
return;
}
bool flg=0;
for(int i=0;i<4;i++){
zt y=x;
y.f^=1;
y.r1x+=fx[i],y.r1y+=fy[i];
if(y.r1x<=0||y.r1x>n||y.r1y<=0||y.r1y>m||a[y.r1x][y.r1y]==-1||(y.r1x==y.r2x&&y.r1y==y.r2y)) continue;//判出界和障碍和红子相撞
else{
flg=1;//红方能动
dfs(y);
nxt[f[y]].pb(f[x]);//反向建图
in[f[x]]++;
}
}
for(int i=0;i<4;i++){
zt y=x;
y.f^=1;
y.r2x+=fx[i],y.r2y+=fy[i];
if(y.r2x<=0||y.r2x>n||y.r2y<=0||y.r2y>m||a[y.r2x][y.r2y]==-1||(y.r1x==y.r2x&&y.r1y==y.r2y)) continue;//判出界和障碍和红子相撞
else{
flg=1;//红方能动
dfs(y);
nxt[f[y]].pb(f[x]);//反向建图
in[f[x]]++;
}
}
if(!flg){//红方不能走就输了,黑赢
q.pb(f[x]);
return;
}
}
}
void topsort(){
while(!q.empty()){
int u=q.front();q.pop_front();
if(u==1){//走到开始的状态
flg=1;//标记走得到起点
break;
}
for(int v:nxt[u]){
in[v]--;
if(!win[u]){//当前状态u是先手输/平局
if(!win[v]){//能到这个状态的v被判定为先手输/平局
win[v]=1;//能到这个状态的v被覆盖为先手赢
dp[v]=dp[u]+1;//步数刷新
q.pb(v);
}
else{//能到这个状态的v被判定为先手赢
dp[v]=min(dp[v],dp[u]+1);//刷新最小步数
}
}
else{//当前状态u是先手赢
if(!win[v]){//当前状态v是先手输/平局
dp[v]=max(dp[v],dp[u]+1);//刷新最大步数
}
}
if(in[v]==0){
q.pb(v);
}
}
}
}
void init(){
for(int i=1;i<N;i++) win[i]=dp[i]=in[i]=0,nxt[i].clear();
int rid1=0,rid2=0,bid=0;
f.clear();
q.clear();
flg=0,cnt=0;//初始化
cin(n),cin(m);
for(int i=1;i<=n;i++){
string s;
cin>>s;
s='%'+s;
for(int j=1;j<=m;j++){
char c=s[j];
a[i][j]=val[c];
if(val[c]==1){
if(rid1) rid2=get(i,j);
else rid1=get(i,j);
}
else if(val[c]==2){
bid=get(i,j);
}
}
}
st.build(0,_get(rid1).x,_get(rid1).y,_get(rid2).x,_get(rid2).y,_get(bid).x,_get(bid).y);//起始状态
}
signed main(){
val['.']=0;
val['#']=-1;
val['O']=1;
val['X']=2;
cin(id);
cin(T);
while(T--){
init();
dfs(st);
topsort();
if(!flg){//走不到起点为平局
puts("Tie");
}
else if(win[1]){//先手赢就是红方赢
printf("Red %d\n",dp[1]);
}
else{
printf("Black %d\n",dp[1]);
}
}
return 0;
}
/*
0 1
3 3
O..
.#X
.O.
*/