#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define INF (1<<25)
int W,H;
char fie[502][502];
int bfs[502][502];
int sps[502][502];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
struct P{
  int x,y,c;
  P(int x,int y,int c) : x(x),y(y),c(c) {}
};
vector<P> p;
vector<P> s;
void BFS(int x,int y){
  queue<P> q;
  q.push(P(x,y,0));
  bfs[x][y]=0;
  while(!q.empty()){
    P p = q.front(); q.pop();
    x = p.x;
    y = p.y;
    int c = p.c;
    for(int i=0;i<4;i++){
      int nx = x+dx[i];
      int ny = y+dy[i];
      if(nx < 0 || ny < 0 || nx>=W || ny>=H) continue;
      if(fie[nx][ny]=='#' || fie[nx][ny]=='*') continue;
      if(bfs[nx][ny]<=c+1) continue;
      bfs[nx][ny]=c+1;
      q.push(P(nx,ny,c+1));
    }
  }
  for(int i=0;i<(int)p.size();i++)
    if(bfs[p[i].x][p[i].y]!=INF) p[i].c = bfs[p[i].x][p[i].y];
}

void BFS2(int x,int y){
  queue<P> q;
  q.push(P(x,y,0));
  sps[x][y]=0;
  while(!q.empty()){
    P p = q.front(); q.pop();
    x = p.x;
    y = p.y;
    int c = p.c;
    for(int i=0;i<4;i++){
      int nx = x+dx[i];
      int ny = y+dy[i];
      if(nx < 0 || ny < 0 || nx>=W || ny>=H) continue;
      if(fie[nx][ny]=='#' || fie[nx][ny]=='*') continue;
      if(sps[nx][ny]<=c+1) continue;
      sps[nx][ny]=c+1;
      q.push(P(nx,ny,c+1));
    }
  }
}
double gosaume(){
  double ret = 0.0f;
  for(int i=0;i<(int)p.size();i++)
    ret += (double)p[i].c;
  ret/=(double)p.size();
  
  return ret;
}
/*
double dp[501][501];
double dpg[50];
int used[501][501];
int useg[50];
double max_d=0.0f;
double solve(int x,int y,int jc){
  if(jc>=48){
    //    used[x][y]=1;
    if(bfs[x][y]==-1) return dp[x][y]=(double)INF;
    return dp[x][y]=(double)bfs[x][y];
  }
  if(jc<10 && used[x][y]) return dp[x][y];
  double ret = 0.0f;
  if(sps[x][y]==-1 || sps[x][y]>=bfs[x][y] || max_d >= bfs[x][y]) return dp[x][y]=(double)bfs[x][y];
  for(int i=0;i<(int)p.size();i++){
    ret += (solve(p[i].x,p[i].y,jc+1)+(double)sps[x][y]);
  }
  ret = min((double)(bfs[x][y]>0?bfs[x][y]:INF),ret/(double)p.size());
  //  printf("st :: %d %d %d ,  %lf %lf\n",x,y,jc,ret,(double)bfs[x][y]); 
  used[x][y]=1;
  return dp[x][y]=ret;
  }*/
double dp[2][250000];
double solve(){
  double max_d=0.0f;
  int co=0;
  for(int i=0;i<(int)p.size();i++){
    if(p[i].c!=INF){
      max_d += (double)p[i].c; co++;
    }
  }
  max_d/=(double)co;

  //  printf("%lf\n",max_d);

  for(int id = 0; id < (int)p.size(); id++)
    dp[0][id] = min((double)bfs[p[id].x][p[id].y],max_d);
  
  for(int i=50;i>1;i--){
    int now = i&1;
    int next = (now+1)&1;

    max_d = 0.0f;
    for(int id = 0; id < (int)p.size(); id++){
      // printf("before::dp[%d][%d] = %lf\n",i,id,dp[now][id]);
      max_d += dp[now][id];
      dp[next][id]=0.0f;
    }
    
    //    printf("%lf\n",max_d);

    for(int id = 0; id < (int)p.size(); id++){
      int x = p[id].x, y = p[id].y;
      double tmp_max = max_d+(double)p.size()*(double)sps[x][y];
      tmp_max/=(double)p.size();
      //      printf("dp[%d][%d] => %lf  VS  %d\n",i,id,tmp_max,bfs[x][y]);
      if(sps[x][y]==INF){
	dp[next][id] += (double)bfs[x][y];
      } else if(bfs[x][y]==INF){
	dp[next][id] += tmp_max;
      } else{
	dp[next][id] += min((double)bfs[x][y],tmp_max);
      }
      //      printf("after::dp[%d][%d] => %lf\n",i-1,id,dp[next][id]);
    }
  }
}
int main(){
  int gx,gy;
  int sx,sy;
  int ID;
  cin >> W >> H;
  for(int i=0;i<501;i++){
    for(int j=0;j<501;j++){
      bfs[j][i]=INF;
      sps[j][i]=INF;
    }
  }
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      cin >> fie[j][i];
      if(fie[j][i]=='.' || fie[j][i]=='s') p.push_back(P(j,i,INF));
      if(fie[j][i]=='s'){ sx = j; sy = i; ID = p.size()-1; }
      if(fie[j][i]=='g'){ gx = j; gy = i; }
      if(fie[j][i]=='*') s.push_back(P(j,i,0));
    }
  }
  BFS(gx,gy);
  for(int i=0;i<(int)s.size();i++) BFS2(s[i].x,s[i].y);
  solve();
  printf("%.12lf\n",dp[0][ID]);
}

Measured memory_bytes: 10320