#include <bits/stdc++.h>
using namespace std;
constexpr int INF = 87654321;
class Fenwick {
 public:
  vector<int> tree;
  int length;
  int Rmq(int i) {
    int ret = INF;
    while (i) {
      ret = min(ret, tree[i]);
      i -= i & -i;
    }
    return ret;
  }
  void Update(int i, int val) {
    while (i <= length) {
      tree[i] = min(tree[i], val);
      i += i & -i;
    }
  }
  Fenwick() {}
  Fenwick(int length) : tree(length + 1, INF), length(length) {}
  void reset() {
    for (int i = 0; i < length + 1; ++i) tree[i] = INF;
  }
};
int n, m, p;
Fenwick fenwick[4];
vector<vector<int>> board, dp;
vector<vector<pair<int, int>>> idx;
vector<vector<pair<int, int>>> level[4], true_idx[4];
void Solve() {
  for (int x = 0; x < 4; ++x) {
    fenwick[x] = Fenwick(m);
    level[x].clear();
    level[x].resize(p + 1);
    true_idx[x].clear();
    true_idx[x].resize(p + 1);
    vector<pair<int, pair<pair<int, int>, pair<int, int>>>> chest;
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= m; ++j) {
        chest.push_back({board[i][j], {{i, j}, idx[i][j]}});
      }
    }
    sort(chest.begin(), chest.end());
    for (int i = 0; i < n * m; ++i) {
      level[x][chest[i].first].push_back(chest[i].second.first);
      true_idx[x][chest[i].first].push_back(chest[i].second.second);
    }
    vector<vector<int>> rotated_board(m + 1, vector<int>(n + 1, 0));
    vector<vector<pair<int, int>>> rotated_idx(
        m + 1, vector<pair<int, int>>(n + 1, {0, 0}));
    for (int j = 1; j <= m; ++j) {
      for (int i = 1; i <= n; ++i) {
        rotated_board[j][i] = board[n + 1 - i][j];
        rotated_idx[j][i] = idx[n + 1 - i][j];
      }
    }
    board = rotated_board;
    idx = rotated_idx;
    swap(n, m);
  }
  dp = vector<vector<int>>(n + 1, vector<int>(m + 1, INF));
  dp[level[0][p][0].first][level[0][p][0].second] = 0;
  for (int v = p - 1; v >= 1; --v) {
    for (int x = 0; x < 4; ++x) {
      auto& cur_tree = fenwick[x];
      cur_tree.reset();
      const auto& query = level[x][v];
      const auto& data = level[x][v + 1];
      const auto& query_idx = true_idx[x][v];
      const auto& data_idx = true_idx[x][v + 1];
      int i = 0, j = 0;
      while (i < query.size()) {
        while (j < data.size() && (data[j].first < query[i].first ||
                                   (data[j].first == query[i].first &&
                                    data[j].second < query[i].second))) {
          cur_tree.Update(data[j].second,
                          dp[data_idx[j].first][data_idx[j].second] -
                              data[j].first - data[j].second);
          ++j;
        }
        auto& val = dp[query_idx[i].first][query_idx[i].second];
        val = min(val, cur_tree.Rmq(query[i].second) + query[i].first +
                           query[i].second);
        ++i;
      }
    }
  }
}
int main() {
  scanf("%d%d%d", &n, &m, &p);
  board = vector<vector<int>>(n + 1, vector<int>(m + 1, 0));
  idx = vector<vector<pair<int, int>>>(n + 1,
                                       vector<pair<int, int>>(m + 1, {0, 0}));
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      scanf("%d", &board[i][j]);
      idx[i][j] = {i, j};
    }
  }
  Solve();
  int ans = INF;
  for (int i = 0; i < level[0][1].size(); ++i) {
    ans = min(ans, dp[level[0][1][i].first][level[0][1][i].second] +
                       abs(level[0][1][i].first - 1) +
                       abs(level[0][1][i].second - 1));
  }
  printf("%d\n", ans);
  return 0;
}
