#include <iostream>
#include <iomanip>
#include <vector>
#include <queue>

using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;
constexpr int dir[5] = {0, 1, 0, -1, 0};

int main()
{
    ll W, H;
    cin >> W >> H;
    vector<vector<char>> field(H, vector<char>(W));
    P s, g;
    vector<P> spring;
    ll floor = 0;
    for (ll i = 0; i < H; i++) {
        for (ll j = 0; j < W; j++) {
            cin >> field[i][j];
            if (field[i][j] == 's') {
                s = make_pair(i, j);
                field[i][j] = '.';
                floor++;
            } else if (field[i][j] == 'g') {
                g = make_pair(i, j);
            } else if (field[i][j] == '*') {
                spring.push_back(make_pair(i, j));
            } else if (field[i][j] == '.') {
                floor++;
            }
        }
    }

    constexpr ll INF = 1LL << 60;
    vector<vector<ll>> goal_dist(H, vector<ll>(W, INF));
    vector<vector<ll>> spring_dist(H, vector<ll>(W, INF));
    vector<vector<bool>> used(H, vector<bool>(W, false));
    queue<pair<P, ll>> q;
    q.push(make_pair(g, 0));
    while (not q.empty()) {
        const auto& s = q.front();
        const ll y = s.first.first;
        const ll x = s.first.second;
        const ll dist = s.second;
        q.pop();
        used[y][x] = true;
        goal_dist[y][x] = dist;
        for (ll d = 0; d < 4; d++) {
            const ll newx = x + dir[d];
            const ll newy = y + dir[d + 1];
            if (newx >= 0 and newx < W and newy >= 0 and newy < H and (not used[newy][newx]) and (field[newy][newx] == '.')) {
                used[newy][newx] = true;
                q.push(make_pair(make_pair(newy, newx), dist + 1));
            }
        }
    }

    fill(used.begin(), used.end(), vector<bool>(W, false));
    for (const P& sp : spring) {
        q.push(make_pair(sp, 0));
    }

    while (not q.empty()) {
        const auto& s = q.front();
        const ll y = s.first.first;
        const ll x = s.first.second;
        const ll dist = s.second;
        q.pop();
        used[y][x] = true;
        spring_dist[y][x] = dist;
        for (ll d = 0; d < 4; d++) {
            const ll newx = x + dir[d];
            const ll newy = y + dir[d + 1];
            if (newx >= 0 and newx < W and newy >= 0 and newy < H and (not used[newy][newx]) and (field[newy][newx] == '.')) {
                used[newy][newx] = true;
                q.push(make_pair(make_pair(newy, newx), dist + 1));
            }
        }
    }

    ld inf = 0;
    ld sup = 10000000000;
    constexpr ll REP = 1000;
    for (ll i = 0; i < REP; i++) {
        const ld mid = (inf + sup) / 2;
        ld sum = 0;
        for (ll y = 0; y < H; y++) {
            for (ll x = 0; x < W; x++) {
                if (field[y][x] == '.') {
                    sum += min(spring_dist[y][x] + mid, (ld)goal_dist[y][x]);
                }
            }
        }
        const ld actual = sum / floor;
        if (actual < mid) {
            sup = mid;
        } else {
            inf = mid;
        }
    }

    const ll sy = s.first;
    const ll sx = s.second;
    cout << fixed << setprecision(15) << min(spring_dist[sy][sx] + inf, (ld)goal_dist[sy][sx]) << endl;

    return 0;
}

Measured memory_bytes: 7452