import std.conv;
import std.stdio;
import std.string;
import std.typecons;
import std.algorithm;
import std.container;
import std.functional;

int x,y;
int[] cost;

int dijkstra(Tuple!(int, int) s, Tuple!(int, int) g){
	BinaryHeap!(Array!(Tuple!(int,Tuple!(int,int))), "a[0]>=b[0]") que;
	que.insert(tuple(0, s));
	int[] dist = new int[](cost.length);
	dist[] = int.max;
	while(!que.empty()){
		Tuple!(int,Tuple!(int,int)) top = que.front();
		que.removeFront();
		if(cost[top[1][0]+x*top[1][1]] < int.max && dist[top[1][0]+x*top[1][1]] > top[0]){
			dist[top[1][0]+x*top[1][1]] = top[0];
			foreach(i; -1..2){
				foreach(j; -1..2){
					if((i==0||j==0) && i+top[1][0]>=0 && i+top[1][0]<x && j+top[1][1]>=0 && j+top[1][1]<y){
						que.insert(tuple(cost[top[1][0]+x*top[1][1]] + top[0], tuple(i+top[1][0], j+top[1][1])));
					}
				}
			}
		}
		
	}
	return dist[g[0]+x*g[1]];
}
int main(){
	auto ln = map!(to!int)(readln.strip.split(" "));
	x = ln[1];
	y = ln[0];
	cost = new int[](x*y);
	cost[] = 1;
	Tuple!(int, int)[] m;
	Tuple!(int, int) s, g;
	foreach(i; 0..x){
		string a = readln;
		foreach(j; 0..y){
			if(a[j]=='S') s = tuple(i, j);
			else if(a[j]=='G') g = tuple(i, j);
			else if(a[j]=='M') m ~= tuple(i, j);
			else if(a[j]=='#'){
				foreach(k; -2..3){
					foreach(l; -2..3){
						if(i+k>=0 && i+k<x && j+l>=0 && j+l<y){
							cost[i+k+x*(j+l)] = max(cost[i+k+x*(j+l)], (k==2||k==-2||l==2||l==-2 ? 2 : 3));
						}
					}
				}
				cost[i+x*j] = int.max;
			}
		}
	}
	int ans = int.max;
	int[] pe;
	foreach(i; 0..m.length) pe ~= cast(int)(i);
	do{
		int route = memoize!(dijkstra)(s, m[pe[0]]) + memoize!(dijkstra)(m[pe[pe.length-1]], g);
		for(int i=1; i<pe.length; i++){
			route += memoize!(dijkstra)(m[pe[i-1]], m[pe[i]]);
		}
		ans = min(ans, route);
	}while(nextPermutation(pe));
	ans.writeln;
	return 0;
}