/* Author:zeke pass System Test! GET AC!! */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using ll = long long; using ld = long double; using namespace std; #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define all(x) (x).begin(), (x).end() #define rep3(var, min, max) for (ll(var) = (min); (var) < (max); ++(var)) #define repi3(var, min, max) for (ll(var) = (max)-1; (var) + 1 > (min); --(var)) #define Mp(a, b) make_pair((a), (b)) #define F first #define S second #define Icin(s) \ ll(s); \ cin >> (s); #define Scin(s) \ ll(s); \ cin >> (s); template bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; } template bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; } typedef pair P; typedef vector V; typedef vector VV; typedef vector

VP; ll mod = 1e9 + 7; ll MOD = 1e9 + 7; const int INF = 7 + (1e+9); typedef int Weight; struct Edge { //src:辺の始点,dst:辺の終点,weight:辺の重さ int src, dst; Weight weight; Edge(int src, int dst, Weight weight) : src(src), dst(dst), weight(weight) {} }; bool operator<(const Edge &e, const Edge &f) { return e.weight != f.weight ? e.weight > f.weight : //辺は重さが重いものを"小さい"と定義する e.src != f.src ? e.src < f.src : e.dst < f.dst; } typedef vector Edges; typedef vector Graph; //引数 g:隣接リスト,s:始点,dist:各頂点までの距離が入る,prev:最短路木の親頂点が入る //戻値 なし void shortestPath(const Graph &g, int s, vector &dist, vector &prev) { int n = g.size(); dist.assign(n, INF); dist[s] = 0; prev.assign(n, -1); priority_queue Q; Q.push(Edge(-2, s, 0)); while (!Q.empty()) { Edge e = Q.top(); Q.pop(); if (prev[e.dst] != -1) continue; prev[e.dst] = e.src; for (auto f = g[e.dst].begin(); f != g[e.dst].end(); f++) { if (dist[f->dst] > e.weight + f->weight) { dist[f->dst] = e.weight + f->weight; Q.push(Edge(f->src, f->dst, e.weight + f->weight)); } } } } //引数 prev:最短路木の親頂点集合,t:終点 //戻値 path:sからtへの最短経路 vector buildPath(const vector &prev, int t) { vector path; for (int u = t; u >= 0; u = prev[u]) path.push_back(u); reverse(path.begin(), path.end()); return path; } /*int main() { // ... Graph g(v); //頂点数vの空隣接リストgを生成 // ... g[s].push_back(Edge(s, t, w)); //隣接リストgにsからtに向かう重さwの辺を追加 // ... vector dist; vector prev; shortestPath(g, 0, dist, prev); // ... }*/ int main() { cin.tie(0); ios::sync_with_stdio(false); ll h, w; cin >> h >> w; Graph g(h * w + 10); VV temp(h, V(w)); int dx[] = {-1, 0}; int dy[] = {0, -1}; rep(i, h) { string s; cin >> s; rep(j, w) { rep(k, 2) { if (i + dy[k] >= 0 && i + dy[k] < h && j + dx[k] >= 0 && j + dx[k] < w) { ll temp1 = i * w + j; ll temp2 = (i + dy[k]) * w + (j + dx[k]); ll weight = i + j + 1; if (s[j] == '.') { g[temp2].push_back(Edge(temp2, temp1, 1)); } else { g[temp2].push_back(Edge(temp2, temp1, weight)); } } } } } vector dist; vector prev; shortestPath(g, 0, dist, prev); cout << dist[h * w - 1] << endl; }