这题与平常的迷宫题不太相像啊。。。
不过可以告诉大家,还是\(\text{BFS}\)。
有一点要注意的是:\(\text{Malon}\)走到\((r,c)\)的时候,\(\text{Gurin}\)却不一定走到此处,反之亦然。所以这题只用\(2\)维的\(vis\)标记数组是不够的。
\(\color{blue}\colorbox{yellow}{开四维!!!}\)
定义:\(\text{vis[i][j][k][h]表示Gurin走到(i,j)时,Malon走到(k,h)时的状态是否出现。}\) 这样一个问题就解决了。
还有一个比较繁琐的问题就是:\(\text{蜘蛛网and墙的判断。}\)
下面的代码中的\(adjust\)函数就是处理这个的\(--\)
在前面先移动(暂时不管墙),在\(adjust\)中,如果出墙了,就退回来。如果走了等于没走,在下面的\(check\)中会自动过滤掉。
还有就是方向数组的控制,\(\text{注意是左右相反,上下相同的。}\)
结构体别忘了定义哦~
贴标程:
#include
#include
#include
using namespace std;
struct node
{
int Mx,My;
int Gx,Gy;
int step;
};
const int dyI[5]={0,0,0,1,-1},dxI[5]={0,-1,1,0,0};//Gurin
const int dyII[5]={0,0,0,-1,1},dxII[5]={0,-1,1,0,0};//Malon
int m,n;
char map[31][31];
bool vis[31][31][31][31];
int min(int temp_x,int temp_y)
{
if(temp_x>temp_y)
return temp_y;
return temp_x;
}
bool Check(node chk)
{
if(chk.Gx >n||chk.Gx <1||chk.Mx >n||chk.Mx <1||chk.Gy >m||chk.Gy <1||chk.My >m||chk.My <1)
return 0;
if(map[chk.Gx ][chk.Gy ]=='X'||map[chk.Mx ][chk.My ]=='X')
return 0;
if(vis[chk.Gx ][chk.Gy ][chk.Mx ][chk.My ])
return 0;
return 1;
}
void adjust(node &adj,int index)
{
if(map[adj.Gx ][adj.Gy ]=='#')
adj.Gx -=dxI[index],adj.Gy -=dyI[index];
if(map[adj.Mx ][adj.My ]=='#')
adj.Mx -=dxII[index],adj.My -=dyII[index];
return;
}
int Bfs(node start)
{
vis[start.Gx ][start.Gy ][start.Mx ][start.My ]=1;
queueQ;
Q.push(start);
while(!Q.empty())
{
node now=Q.front();
Q.pop();
if(map[now.Gx ][now.Gy ]=='T'&&map[now.Mx ][now.My ]=='T')
return now.step ;
for(int i=1;i<=4;i++)
{
node tmp=now;
tmp.Gx +=dxI[i],tmp.Gy +=dyI[i];
tmp.Mx +=dxII[i],tmp.My +=dyII[i];
tmp.step ++;
adjust(tmp,i);
if(Check(tmp))
{
vis[tmp.Gx ][tmp.Gy ][tmp.Mx ][tmp.My ]=1;
Q.push(tmp);
}
}
}
return -1;
}
int main()
{
node start;
start.step =0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='G')
start.Gx =i,start.Gy =j;
if(map[i][j]=='M')
start.Mx =i,start.My =j;
}
int ans=Bfs(start);
if(ans!=-1)
cout<