#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef pair<int,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const ld MAX = 10000000000000;
const ld EPS = 0.0000000001;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

int main(){
	static int w,h;
	static char c[502][502];
	scanf("%d%d",&w,&h);
	rep(i,h){
		scanf("\n");
		rep(j,w){
			scanf("%c",&c[i][j]);
		}
	}
	
	static ld a[502][502];
	static bool used[502][502];
	static queue<pair<ld,P>> que;
	rep(i,h)rep(j,w){
		if(c[i][j] == 'g'){
			a[i][j] = 0;
			que.push(pair<ld,P>(0,P(i,j)));
		}
		else a[i][j] = MAX;
		used[i][j] = false;
	}
	while(!que.empty()){
		pair<ld,P> p = que.front(); que.pop();
		if(!used[p.sc.fr][p.sc.sc]){
			rep(i,4){
				int nx = p.sc.fr + dir_4[i][0];
				int ny = p.sc.sc + dir_4[i][1];
				if(c[nx][ny] == '#' || c[nx][ny] == '*')continue;
				if(a[nx][ny] > a[p.sc.fr][p.sc.sc] + 1.0){
					a[nx][ny] = a[p.sc.fr][p.sc.sc] + 1.0;
					que.push(pair<ld,P>(a[nx][ny],P(nx,ny)));
				}
			}
			used[p.sc.fr][p.sc.sc] = true;
		}
	}
	
	static ld b[502][502];
	rep(i,h)rep(j,w){
		if(c[i][j] == '*'){
			b[i][j] = 0;
			que.push(pair<ld,P>(0,P(i,j)));
		}
		else b[i][j] = MAX;
		used[i][j] = false;
	}
	while(!que.empty()){
		pair<ld,P> p = que.front(); que.pop();
		if(!used[p.sc.fr][p.sc.sc]){
			rep(i,4){
				int nx = p.sc.fr + dir_4[i][0];
				int ny = p.sc.sc + dir_4[i][1];
				if(c[nx][ny] == '#' || c[nx][ny] == '*')continue;
				if(b[nx][ny] > b[p.sc.fr][p.sc.sc] + 1.0){
					b[nx][ny] = b[p.sc.fr][p.sc.sc] + 1.0;
					que.push(pair<ld,P>(b[nx][ny],P(nx,ny)));
				}
			}
			used[p.sc.fr][p.sc.sc] = true;
		}
	}
	
	bool t = false;
	rep(i,h)rep(j,w){
		if(c[i][j] == 's' && b[i][j] == MAX)t = true;
	}
	rep(i,h)rep(j,w){
		if(a[i][j] == MAX && b[i][j] == MAX)c[i][j] = '#';
		if(t && a[i][j] == MAX)c[i][j] = '#';
	}
	
	cout.precision(20);
	ld l = 0.0 , r = MAX;
	rep(ppp,200){
		ld m = (l+r)/2;
		ld sum = 0.0 , cnt = 0.0;
		rep(i,h)rep(j,w){
			if(c[i][j] == '#' || c[i][j] == '*' || c[i][j] == 'g')continue;
			sum += min ( a[i][j] , m+b[i][j] );
			cnt += 1.0;
		}
		//cout << l << " " << r << ":" << endl;
		//cout << "m = " << m << endl;
		//cout << "sum = " << sum << ",cnt = " << cnt << endl;
		if(m*cnt > sum)r = m;
		else l = m;
	}
	
	/*rep(i,h){
		rep(j,w){
			if(a[i][j] >= MAX-1.0){
				printf("-");
			}
			else {
				printf("%d",(int)a[i][j]);
			}
		}
		puts("");
	}
	rep(i,h){
		rep(j,w){
			if(b[i][j] >= MAX-1.0){
				printf("-");
			}
			else {
				printf("%d",(int)b[i][j]);
			}
		}
		puts("");
	}*/
	
	cout.precision(20);
	rep(i,h)rep(j,w){
		if(c[i][j] == 's'){
			cout << min ( a[i][j] , l+b[i][j] ) << endl;
		}
	}
}

Measured memory_bytes: 10556