#include <set>
#include <cstdio>
#include <queue>
#include <algorithm>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

#define IN(x,s,g) ((x) >= (s) && (x) < (g))
#define ISIN(x,y,w,h) (IN((x),0,(w)) && IN((y),0,(h)))

using namespace std;

int w, h;
char g[512][512];

int sx, sy;
int gx, gy;
int all;

int dg[512][512];
int ds[512][512];

const int _dx[] = {0,1,0,-1};
const int _dy[] = {-1,0,1,0};


int main(){
  scanf("%d%d", &w, &h);
  REP(i,h) scanf("%s", g[i]);

  queue<pair<int, int> > gq;
  queue<pair<int, int> > sq;

  REP(i,h) REP(j,w){
    dg[i][j] = ds[i][j] = -1;

    if(g[i][j] == '.' || g[i][j] == 's')
      all++;

    if(g[i][j] == 's'){
      sx = j; sy = i;
      g[i][j] = '.';
    }else if(g[i][j] == 'g'){
      gx = j; gy = i;
      gq.push(make_pair(i, j));
      dg[i][j] = 0;
    }else if(g[i][j] == '*'){
      sq.push(make_pair(i, j));
      ds[i][j] = 0;
    }
  }

  // bfs1
  while(gq.size()){
    int x = gq.front().second;
    int y = gq.front().first;
    gq.pop();

    REP(i,4){
      int xx = x + _dx[i];
      int yy = y + _dy[i];
      if(ISIN(xx, yy, w, h) &&
         dg[yy][xx] == -1   &&
         g[yy][xx] == '.'){
        dg[yy][xx] = dg[y][x] + 1;
        gq.push(make_pair(yy, xx));
      }
    }
  }

  // REP(i,h){ REP(j,w) printf("%2d ", dg[i][j]); puts(""); }

  // bfs2
  while(sq.size()){
    int x = sq.front().second;
    int y = sq.front().first;
    sq.pop();

    REP(i,4){
      int xx = x + _dx[i];
      int yy = y + _dy[i];
      if(ISIN(xx, yy, w, h) &&
         ds[yy][xx] == -1   &&
         g[yy][xx] == '.'){
        ds[yy][xx] = ds[y][x] + 1;
        sq.push(make_pair(yy, xx));
      }
    }
  }

  // REP(i,h) { REP(j,w) printf("%2d ", ds[i][j]); puts(""); }

  double ans = 1e10;
  int cnt = 0;
  long long chokusetsu = 0;
  long long tospring   = 0;

  if(dg[sy][sx] != -1) ans = dg[sy][sx];

  // spring = p * chokusetsu + (1 - p) * (tospring + spring)
  // p * spring = p * chokusetsu + (1 - p) * tospring
  // spring = chokusetsu + (1 - p) / p * tospring

  vector<pair<int, pair<int, int> > > pos;
  REP(i,h) REP(j,w) if(g[i][j] == '.'){
    int d = dg[i][j];
    if(d == -1){
      tospring += ds[i][j];
    }else{
      chokusetsu += d;
      cnt++;
      int dd = ds[i][j];
      if(dd != -1 && dd < d){
        pos.push_back(make_pair(-(d - dd), make_pair(i, j)));
      }
    }
  }

  sort(pos.begin(), pos.end());

  size_t idx = 0;

  while(idx != pos.size() && cnt != 0){
    double p = (double)cnt / all;

    // printf("cnt: %d, all: %d, ans: %.3f\n", cnt, all, ans);
    if(cnt != all && ds[sy][sx] != -1)
      ans = min(ans, ds[sy][sx] + (double)chokusetsu / cnt
                + (1 - p) / p * ((double)tospring / (all - cnt)));

    int d = pos[idx].first;

    while(idx != pos.size() && pos[idx].first == d){
      int x = pos[idx].second.second;
      int y = pos[idx].second.first;

      if(ds[y][x] != -1){
        cnt--;
        chokusetsu -= dg[y][x];
        tospring   += ds[y][x];
      }
      idx++;
    }

  }

  double p = (double)cnt / all;
  if(cnt != 0 && cnt != all && ds[sy][sx] != -1)
    ans = min(ans, ds[sy][sx] + (double)chokusetsu / cnt
              + (1 - p) / p * ((double)tospring / (all - cnt)));
  printf("%.10f\n", ans);

  return 0;
}

Measured memory_bytes: 0