﻿#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <unordered_set>
//#include <bits/extc++.h>

#include <unordered_map>

//#pragma GCC optimize("O3")
#pragma GCC target("sse,sse2,sse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
//#define sz(x) signed(x.size())
#define db(x) cout << #x << " " << x << endl
#define int long long
using namespace std;

//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
//using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;

//mt19937 rnd(505);
const int INF = 1e9 + 7;
//#define int long double

struct Node{
    int x, y, coun;
    Node (int a, int b, int c) {
        x = a;
        y = b;
        coun = c;
    }
};


signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
//    freopen("river.in", "r", stdin);
//    freopen("river.out", "w", stdout);
//    cout.precision(37);
    int n, m, w;
    cin >> n >> m >> w;
    vector <vector <int>> field(n, vector <int> (m));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) cin >> field[i][j];
    }
    queue<Node> que;
    vector <vector <int>> dist(n, vector <int> (m, -1));
    que.push({0, 0, 0});
    while (!que.empty()) {
        auto [a, b, c] = que.front();
        que.pop();
//        cout << a << " " << b << " " << c << endl;
        if (dist[a][b] != -1 or field[a][b] == -1) continue;
        dist[a][b] = c;
        if (a + 1 < n) que.push({a + 1, b, c + w});
        if (a - 1 >= 0) que.push({a - 1, b, c + w});
        if (b + 1 < m) que.push({a, b + 1, c + w});
        if (b - 1 >= 0) que.push({a, b - 1, c + w});
    }
    vector <vector <int>> dist2(n, vector <int> (m, -1));
    que.push({n - 1, m - 1, 0});
    while (!que.empty()) {
        auto [a, b, c] = que.front();
        que.pop();
        if (dist2[a][b] != -1 or field[a][b] == -1) continue;
        dist2[a][b] = c;
        if (a + 1 < n) que.push({a + 1, b, c + w});
        if (a - 1 >= 0) que.push({a - 1, b, c + w});
        if (b + 1 < m) que.push({a, b + 1, c + w});
        if (b - 1 >= 0) que.push({a, b - 1, c + w});
    }
//    for (int i = 0; i < n; ++i) {
//        for (int j = 0; j < m; ++j) {
//            cout << dist2[i][j] << " ";
//        }
//        cout << endl;
//    }
    int ans_now = 1e17;
    if (dist[n - 1][m - 1] != -1) {
        ans_now = dist[n - 1][m - 1];
    }
    int minn_ans1 = 1e17;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (field[i][j] != -1 and field[i][j] != 0 and dist[i][j] != -1) {
                minn_ans1 = min(minn_ans1, field[i][j] + dist[i][j]);
            }
        }
    }
    int minn_ans2 = 1e17;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (field[i][j] != -1 and field[i][j] != 0 and dist2[i][j] != -1) {
                minn_ans2 = min(minn_ans2, field[i][j] + dist2[i][j]);
            }
        }
    }
    ans_now = min(ans_now, minn_ans2 + minn_ans1);
    if (ans_now == 1e17) cout << -1 << "\n";
    else cout << ans_now;
}