#include #include using namespace std; using namespace atcoder; #define rep(i, n) REP(i, 0, n) #define REP(i, s, e) for (int i = (s); i < (int)(e); i++) #define repr(i, n) REPR(i, n, 0) #define REPR(i, s, e) for (int i = (int)(s - 1); i >= (int)(e); i--) #define all(r) r.begin(), r.end() #define rall(r) r.rbegin(), r.rend() typedef long long ll; typedef vector vi; typedef vector vl; template T chmax(T& a, const U& b) { if (a >= b) return false; a = b; return true; } template T chmin(T& a, const U& b) { if (a <= b) return false; a = b; return true; } void yes_no(bool f, string yes = "Yes", string no = "No") { cout << (f ? yes : no) << "\n"; } void solve() { int w, h; cin >> w >> h; vector s(h, vi(w)); rep(i, h) rep(j, w) cin >> s[i][j]; int dx[] = {0, -1, 0, 1}; int dy[] = {-1, 0, 1, 0}; auto isOutOfRange = [](int h, int w, int H, int W) { return h < 0 || h >= H || w < 0 || w >= W; }; using T = tuple; const int inf = 1e9; const int ma = 11; vector d(h, vector(w, vector(ma, inf))); priority_queue q; rep(i, ma) if (s[0][0] != i) { d[0][0][i] = 0; q.emplace(0, 0, i); } auto iskad = [](int i, int j, int k) { if (i == j || j == k || k == i) return false; vi v{i, j, k}; sort(all(v)); return i == v[1] || k == v[1]; }; while (!q.empty()) { auto [y, x, pre] = q.top(); q.pop(); int cur = s[y][x]; // cout << y << " " << x << " " << pre << " " << cur << '\n'; rep(i, 4) { int nx = x + dx[i], ny = y + dy[i]; if (isOutOfRange(ny, nx, h, w)) continue; int nxt = s[ny][nx]; if (iskad(pre, cur, nxt) && chmin(d[ny][nx][cur], d[y][x][pre] + 1)) { q.emplace(ny, nx, cur); } } } int ans = *min_element(all(d[h - 1][w - 1])); if (ans == inf) ans = -1; cout << ans << "\n"; } int main() { cin.tie(0); ios::sync_with_stdio(false); int t = 1; // multi-testcase // cin >> t; rep(ti, t) solve(); return 0; }