#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<map>
#include<functional>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<climits>
using namespace std;

typedef long long ll;

const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};

struct Data
{
	int x, y, cost;
	Data() {}
	Data(int _x, int _y, int _cost)
	{
		x = _x;
		y = _y;
		cost = _cost;
	}

	bool operator < (const Data &a) const
	{
		return cost > a.cost;
	}
};

int main(){
	int R, C;
	char fld[30][30];
	priority_queue<Data> q;
	cin >> R >> C;
	for (int i = 0; i < R; i++)
	{
		for (int j = 0; j < C; j++)
		{
			cin >> fld[i][j];
			if (fld[i][j] == 'S') q.push(Data(j, i, 0));
		}
	}
	
	Data t;
	bool memo[30][30] = {};
	while (!q.empty())
	{
		t = q.top();
		q.pop();

		//printf("%d, %d, %d\n", t.y, t.x, t.cost);

		if (fld[t.y][t.x] == 'G')
		{
			printf("%d\n", t.cost);
			return 0;
		}

		if (memo[t.y][t.x]) continue;
		memo[t.y][t.x] = true;

		for (int i = 0; i < 4; i++)
		{
			int nx = t.x, ny = t.y;
			for (int j = 1; j <= 3; j++)
			{
				nx += dx[i];
				ny += dy[i];
				if (nx < 0 || C <= nx || ny < 0 || R <= ny || fld[ny][nx] == '#') break;
				int cost = 0;
				if (j >= 2) cost = 2 + j;
				else
				{
					if(fld[ny][nx] == 'o') cost = 1;
					else if(fld[ny][nx] == 'x') cost = 3;
					else cost = 2;
				}

				q.push(Data(nx, ny, t.cost + cost));
			}
		}
	}
	return 0;
}