#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Data{
	Data(){
		row = col = cost = 0;
	}
	Data(int arg_row,int arg_col,int arg_cost){
		row = arg_row;
		col = arg_col;
		cost = arg_cost;
	}
	int row,col,cost;
};

struct Info{
	Info(int arg_row,int arg_col,int arg_cost){
		row = arg_row;
		col = arg_col;
		cost = arg_cost;
	}
	bool operator<(const struct Info &arg) const{
		return cost > arg.cost;
	}
	int row,col,cost;
};

int H,W;

int start_row,start_col,goal_row,goal_col;

int min_cost[30][30],diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
int diff_row_ink[4][3] = {{-1,-2,-3},{1,2,3},{0,0,0},{0,0,0}},diff_col_ink[4][3] = {{0,0,0},{0,0,0},{-1,-2,-3},{1,2,3}};

vector<Data> G[30][30];
char base_map[30][31];


bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){
		scanf("%s",base_map[row]);
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == 'S'){
				start_row = row;
				start_col = col;
				base_map[row][col] = '.';
			}else if(base_map[row][col] == 'G'){
				goal_row = row;
				goal_col = col;
				base_map[row][col] = '.';
			}
		}
	}

	int adj_row,adj_col;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == '#')continue;

			for(int i = 0; i < 4; i++){
				adj_row = row+diff_row[i];
				adj_col = col+diff_col[i];

				if(rangeCheck(adj_row,adj_col) == false || base_map[adj_row][adj_col] == '#' || base_map[adj_row][adj_col] == 'x')continue;

				if(base_map[adj_row][adj_col] == '.'){
					G[row][col].push_back(Data(adj_row,adj_col,2));
				}else if(base_map[adj_row][adj_col] == 'o'){
					G[row][col].push_back(Data(adj_row,adj_col,1));
				}
			}
		}
	}

	for(int dir = 0; dir < 4; dir++){
		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				if(base_map[row][col] == '#')continue;

				for(int i = 0; i < 3; i++){
					adj_row = row+diff_row_ink[dir][i];
					adj_col = col+diff_col_ink[dir][i];

					if(rangeCheck(adj_row,adj_col) == false || base_map[adj_row][adj_col] == '#'){
						break;
					}
					G[row][col].push_back(Data(adj_row,adj_col,2+(i+1)));
				}
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			min_cost[row][col] = BIG_NUM;
		}
	}

	min_cost[start_row][start_col] = 0;

	priority_queue<Info> Q;
	Q.push(Info(start_row,start_col,0));

	Data next;

	while(!Q.empty()){

		if(Q.top().row == goal_row && Q.top().col == goal_col){
			break;
		}else if(Q.top().cost > min_cost[Q.top().row][Q.top().col]){
			Q.pop();
		}else{

			for(int i = 0; i < G[Q.top().row][Q.top().col].size(); i++){
				next = G[Q.top().row][Q.top().col][i];

				if(min_cost[next.row][next.col] > Q.top().cost+next.cost){
					min_cost[next.row][next.col] = Q.top().cost+next.cost;
					Q.push(Info(next.row,next.col,min_cost[next.row][next.col]));
				}
			}
			Q.pop();
		}
	}

	printf("%d\n",min_cost[goal_row][goal_col]);

	return 0;
}



Measured memory_bytes: 3384