60pts
#include <iostream>
#include <cstdio>
#include <queue>
#include <map>
const int N = 8.5e5, R = 30 + 7;
class state {
public:
int xG;
int yG;
int xM;
int yM;
int step;
};
std::queue <state> Q;
state init;
int m[R][R];
std::map <int, bool> visit;
int r, c;
bool die(state p) {
if((m[p.xM][p.yM] == 1) || (m[p.xG][p.yG] == 1)) return true;
else return false;
}
bool win(state p) {
if((m[p.xM][p.yM] == 3) && (m[p.xG][p.yG] == 3)) return true;
else return false;
}
inline bool ok(int x, int y) {
return x > 0 && x <= r && y > 0 && y <= c && (m[x][y] == 2 || m[x][y] == 3);
}
inline int cp(state x) {
return x.xG + x.yG * R + x.xM * R * R + x.yM * R * R * R;
}
state up(state p) {
state temp = p;
if(ok(p.xM - 1, p.yM)) temp.xM--;
if(ok(p.xG - 1, p.yG)) temp.xG--;
temp.step++;
return temp;
}
state down(state p) {
state temp = p;
if(ok(p.xM + 1, p.yM)) temp.xM++;
if(ok(p.xG + 1, p.yG)) temp.xG++;
temp.step++;
return temp;
}
state left(state p) {
state temp = p;
if(ok(p.xM, p.yM - 1)) temp.yM--;
if(ok(p.xG, p.yG + 1)) temp.yG++;
temp.step++;
return temp;
}
state right(state p) {
state temp = p;
if(ok(p.xM, p.yM + 1)) temp.yM++;
if(ok(p.xG, p.yG - 1)) temp.yG--;
temp.step++;
return temp;
}
int main() {
std::cin >> r >> c;
char t[R];
for(int i = 1; i <= r; i++) {
std::cin >> t;
for(int j = 1; j <= c; j++) {
char p = t[j - 1];
if(p == '#') m[i][j] = 0;
else if(p == 'X') m[i][j] = 1;
else if(p == '.') m[i][j] = 2;
else if(p == 'G') init.xG = i, init.yG = j, m[i][j] = 2;
else if(p == 'M') init.xM = i, init.yM = j, m[i][j] = 2;
else m[i][j] = 3;
}
}
init.step = 0;
Q.push(init);
visit[cp(init)] = true;
while(!Q.empty()) {
state u = Q.front();
if(die(u)) continue;
if(win(u)) {
std::cout << u.step << '\n';
return 0;
}
Q.pop();
state p = up(u);
state d = down(u);
state l = left(u);
state r = right(u);
if(!visit[cp(p)] == true) {
Q.push(p);
visit[cp(p)] = true;
}
if(!visit[cp(d)] == true) {
Q.push(d);
visit[cp(d)] = true;
}
if(!visit[cp(l)] == true) {
Q.push(l);
visit[cp(l)] = true;
}
if(!visit[cp(r)] == true) {
Q.push(r);
visit[cp(r)] = true;
}
}
std::cout << "no\n";
return 0;
}