#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <tuple>

using namespace std;
typedef tuple<int, int, int> tiii;
static const int INF = 1000000000;
static const int dx[] = { 1, 0, -1, 0 };
static const int dy[] = { 0, -1, 0, 1 };

inline bool between(int a, int b, int c){
	return a <= b && b < c;
}

int main(){
	ios_base::sync_with_stdio(false);
	int r, c;
	cin >> r >> c;
	vector<string> field(r);
	priority_queue<tiii, vector<tiii>, greater<tiii>> pq;
	vector<vector<int>> dist(r, vector<int>(c, INF));
	for(int i = 0; i < r; ++i){
		cin >> field[i];
		for(int j = 0; j < c; ++j){
			if(field[i][j] == 'S'){
				pq.emplace(0, i, j);
				dist[i][j] = 0;
			}
		}
	}
	int answer = INF;
	while(!pq.empty()){
		const auto t = pq.top();
		pq.pop();
		const int cost = get<0>(t);
		const int y = get<1>(t);
		const int x = get<2>(t);
		if(cost > dist[y][x]){ continue; }
		if(field[y][x] == 'G'){ answer = min(answer, cost); }
		for(int d = 0; d < 4; ++d){
			for(int i = 1; i <= 3; ++i){
				const int ny = y + dy[d] * i, nx = x + dx[d] * i;
				if(!between(0, ny, r) || !between(0, nx, c)){ break; }
				if(field[ny][nx] == '#'){ break; }
				int nc = cost + 2 + i;
				if(i == 1 && field[ny][nx] == 'o'){
					nc = cost + 1;
				}else if(i == 1 && field[ny][nx] != 'x'){
					nc = cost + 2;
				}
				if(nc < dist[ny][nx]){
					dist[ny][nx] = nc;
					pq.emplace(nc, ny, nx);
				}
			}
		}
	}
	cout << answer << endl;
	return 0;
}