#include <bits/stdc++.h>

using namespace std;

namespace {

    typedef long double real;
    typedef long long ll;

    template<class T> ostream& operator<<(ostream& os, const vector<T>& vs) {
        if (vs.empty()) return os << "[]";
        os << "[" << vs[0];
        for (int i = 1; i < vs.size(); i++) os << " " << vs[i];
        return os << "]";
    }
    template<class T> istream& operator>>(istream& is, vector<T>& vs) {
        for (auto it = vs.begin(); it != vs.end(); it++) is >> *it;
        return is;
    }

    int W, H;
    vector<string> F;
    void input() {
        cin >> W >> H;
        F.clear(); F.resize(H);
        cin >> F;
    }

    const real INF = 1e200;
    const int dy[] = {0, -1, 0, 1};
    const int dx[] = {-1, 0, 1, 0};

    vector< vector<real> > C; // from the stairs
    vector< vector<real> > S; // from the nearest spring;

    void bfs(int sy, int sx, vector< vector<real> >& M) {
        assert(M.size() == H && M[0].size() == W);
        queue< pair<int, int> > Q;
        Q.push(make_pair(sy, sx));
        M[sy][sx] = 0;
        while (not Q.empty()) {
            auto cur = Q.front(); Q.pop();
            int cy = cur.first, cx = cur.second;
            for (int i = 0; i < 4; i++) {
                int ny = cy + dy[i],
                    nx = cx + dx[i];
                if (ny < 0 || ny >= H) continue;
                if (nx < 0 || nx >= W) continue;
                if (F[ny][nx] == '#') continue;
                if (F[ny][nx] == '*') continue;
                real ncost = M[cy][cx] + 1;
                if (M[ny][nx] > ncost) {
                    M[ny][nx] = ncost;
                    Q.push(make_pair(ny, nx));
                }
            }
        }
    }

    int N;
    int X, Y;
    void init() {
        N = 0;
        C = vector< vector<real> >(H, vector<real>(W, INF));
        S = vector< vector<real> >(H, vector<real>(W, INF));
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                if (F[i][j] == 'g') {
                    bfs(i, j, C);
                } else if (F[i][j] == '*') {
                    bfs(i, j, S);
                } else if (F[i][j] == 's' || F[i][j] == '.') {
                    if (F[i][j] == 's') {
                        Y = i;
                        X = j;
                    }
                    N++;
                } else {
                    assert(F[i][j] == '#');
                }
            }
        }
    }

    real f(real x) {
        real ret = 0;
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                if (F[i][j] == '.' || F[i][j] == 's') {
                    ret += min(S[i][j] + x, C[i][j]);
                }
            }
        }
        return ret / N;
    }

    real g(real x) {
        return x - f(x);
    }

    void solve() {
        init();
        real lb = 0, ub = INF;
        for (int i = 0; i < 1000; i++) {
            //if (i % 100 == 0) cerr << i << endl;
            real mid = (lb + ub) / 2;
            (g(mid) < 0 ? lb : ub) = mid;
        }
        real x = lb;
        //cerr << "x: " << x << endl;
        //cerr << S[Y][X] << endl;
        cout << fixed << setprecision(12) << min(C[Y][X], S[Y][X] + x) << endl;
    }
}

int main() {
    input(); solve();
    return 0;
}

Measured memory_bytes: 11144