#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
using ll = long long;
#define int ll
using pii = pair<int, int>;
using tiii = tuple<int, int, int>;
template<class T = ll> using V = vector<T>;
template<class T = ll> using VV = V<V<T>>;
#define IOS\
    ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);
#define FOR(i,l,r) for(ll i=(l);i<(r);++i)
#define REP(i,n) FOR(i,0,n)
#define REPS(i,n) FOR(i,1,n+1)
#define RFOR(i,l,r) for(ll i=(l);i>=(r);--i)
#define RREP(i,n) RFOR(i,n-1,0)
#define RREPS(i,n) RFOR(i,n,1)
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define SORT(name) sort(name.begin(), name.end())
#define RSORT(name)\
    SORT(name);\
    reverse(all(name));
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
inline void Yes(bool b = true) {cout << (b ? "Yes" : "No") << '\n';}
inline void YES(bool b = true) {cout << (b ? "YES" : "NO") << '\n';}
template <class T> inline void print(T x){ cout << x << '\n';}
template<typename T1,typename T2> inline void chmin(T1 &a, T2 b){ if(a > b) a = b; }
template<typename T1,typename T2> inline void chmax(T1 &a, T2 b){ if(a < b) a = b; }

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
#pragma endregion

#if 1
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

int H, W, K;
int X1, Y1, X2, Y2;
V<string> C;

enum Direction { Center = 0, Up, Down, Left, Right };

// 二次元配列の各インデックスに一意の id を振ります
class PosId2D {
    public:
        PosId2D() : m_H(0), m_W(0) {}
        PosId2D(ll h, ll w) : m_H(0), m_W(0) { Init(h, w); }
        void Init(ll h, ll w) { m_H = h; m_W = w; }

        // id からそれに対応する (i, j) を返します
        pair<ll, ll> GetPos(ll id) {
            assert(m_H > 0 && m_W > 0);
            return make_pair(id / m_W, id % m_W);
        }
        // i, j からそれに対応する id を返します
        ll GetId(ll i, ll j) {
            return i * m_W + j;
        }
        ll GetId(pair<ll, ll> pos) { return GetId(pos.first, pos.second); }

        // 二次元グリッド上に存在しない特別な id を返します
        // n: 何番目の特別な id か（特別な id が複数作れるように渡す）
        ll GetSpecial(ll n) { return m_H * m_W + n; }

    private:
        ll m_H; // 高さ
        ll m_W; // 幅
};

template <typename T>
class Dijkstra {
    public:
        // コンストラクタ
        // v … 頂点数, state … 各頂点がもつ状態の数 [0, state), inf: …「無限大」とする値
        Dijkstra() {}
        Dijkstra(int v, int state, T inf) { Init(v, state, inf); }
        void Init(int v, int state, T inf) {
            assert(v > 0);
            assert(state > 0);
            m_N = v;
            m_State = state;
            m_MulN = m_N * m_State;
            m_Inf = inf;
            m_Graph.assign(m_MulN, vector< pair<int, T> >());
        }
        // 有向辺の追加。負のコストは未対応
        void AddDirEdge(int from_node, int from_state, int to_node, int to_state, T cost) {
            assert(0 <= from_node && from_node < m_N);
            assert(0 <= to_node && to_node < m_N);
            assert(0 <= from_state && from_state < m_State);
            assert(0 <= to_state && to_state < m_State);
            int from = from_node * m_State + from_state;
            int to = to_node * m_State + to_state;
            m_Graph[from].push_back(make_pair(to, cost));
        }
        // 始点 s , 状態 s_state から各頂点への最短経路の導出 O(E log V)
        void Calc(int s, int s_state) {
            assert(0 <= s && s < m_N);
            assert(0 <= s_state && s_state < m_State);
            m_Dist.assign(m_MulN, m_Inf);
            m_PrevP.assign(m_MulN, -1);
            // 最短距離が短い順で cand を取り出す
            // pair<int, int> 小さい順の priority_queue(間に vector を入れないと昇順にならない)
            // この pair は (first: second 到達までのコスト, second: 頂点id)
            priority_queue<pair<T, int>, vector< pair<T, int> >, greater< pair<T, int> > > cand;
            s = s * m_State + s_state;
            m_Dist[s] = T();  // 始点のコストは 0
            cand.push(make_pair(m_Dist[s], s));
            while(!cand.empty()) {
                pair<T, int> p = cand.top(); cand.pop();     // cand のトップを取り出す
                int v = p.second;
                // 頂点 v まで最短経路が、 cand から取り出したものより既に小さいなら何もしない
                if(m_Dist[v] < p.first){ continue; }
                // 現在見ている頂点から延びている辺を全て見る
                for(const auto& e : m_Graph[v]) {
                    int next_node = e.first;    // 次行くとこ
                    auto cost = e.second;       // v -> next_node のコスト
                    // ****************************************************************
                    // v を経由して、始点から次の頂点に行くときのコスト
                    // T に pair などを利用している場合はここを書き換えなければならない
                    // ****************************************************************
                    //auto next_cost = m_Dist[v] + cost;
                    int v_id = v / m_State;                 // ノード id
                    int v_state = v % m_State;              // v_node の状態
                    int next_id = next_node / m_State;      // 次いくとこの id
                    int next_state = next_node % m_State;   // 次いくとこの状態
                    pii next_cost = mp(m_Dist[v].first + cost.first, m_Dist[v].second + cost.second);
                    if (next_cost.second >= K) {
                        next_cost.first++;
                        next_cost.second = 0;
                    }
                    if(v_state != next_state) {
                        // 方向転換後最初の 1 回は無料にする
                        next_cost.second = -1;
                    }
                    //DBG("(%lld, %lld) -> (%lld, %lld)\n", v_id, v_state, next_id, next_state);
                    //DBG("  cur: (%lld, %lld)\n", m_Dist[next_node].first, m_Dist[next_node].second);
                    //DBG("  cand: (%lld, %lld)\n", next_cost.first, next_cost.second);
                    // ****************************************************************
                    if(m_Dist[next_node] > next_cost) {
                        // 現在の最短経路より短くなるなら更新
                        m_Dist[next_node] = next_cost;
                        m_PrevP[next_node] = v;
                        cand.push(make_pair(m_Dist[next_node], next_node));
                    }
                }
            }
        }
        // 始点 s の状態 s_state から頂点 t の状態 t_state への最短距離を返す O(1)
        // 前処理として Calc(s, s_state) が必要
        T GetDist(int t, int t_state) { return m_Dist[t * m_State + t_state]; }
        // 始点 s の状態 s_state から頂点 t の状態 t_state までの経路を vector に入れて返す (s と t 含む)
        // O(V') … V' は最短経路の頂点数
        // 前処理として Calc(s, s_state) が必要
        vector< pair<int, int> > GetPath(int t, int t_state) {
            vector< pair<int, int> > path;
            t = t * m_State + t_state;
            for(; t != -1; t = m_PrevP[t]) {
                path.push_back(make_pair(t / m_State, t % m_State));
            }  // t が s になるまで prev_p[t] を辿っていく
            // このままだと t->s の順になっているので逆順にする
            reverse(path.begin(), path.end());
            return path;
        }
    private:
        int m_N;                    // 倍化前の頂点の数
        int m_MulN;                 // 倍化後の頂点の数( = 元の頂点の数 * 状態の数)
        int m_State;                // 状態の数
        T m_Inf;                  // 無限の代わりとして扱う値
        // 頂点 i から延びている辺の vector(隣接リスト) first: 行先 second: コスト
        vector< vector< pair<int, T> > > m_Graph;
        vector<T> m_Dist;         // 各頂点への最短コスト。つまり答え
        vector<int> m_PrevP;        // 最短経路の各頂点を保存(経路復元で利用)
};

const int MOD = 1000000007;
const int MAX_N = 100010;

signed main() {
    IOS;

    cin >> H >> W >> K;
    cin >> X1 >> Y1 >> X2 >> Y2;
    X1--; Y1--; X2--; Y2--;
    C.resize(H);
    REP(i, H) {
        cin >> C[i];
    }

    // first: 移動した数、 second: 同じ方向に移動した数
    Dijkstra<pii> dk(H * W, 5, mp(LLINF, LLINF));
    PosId2D pi(H, W);

    REP(i, H) {
        REP(j, W) {
            if(C[i][j] == '@') { continue; }
            int id = pi.GetId(i, j);
            REP(k, 5) {
                if(k == Center) { continue; }
                // 方向転換する場合
                dk.AddDirEdge(id, k, id, Center, pii(0, 0));
                dk.AddDirEdge(id, Center, id, k, pii(1, 0));
                // 同じ向きに移動する場合
                pii cost = mp(0, 1);
                if(k == Up && i > 0 && C[i- 1][j] == '.') {
                    int next_id = pi.GetId(i - 1, j);
                    dk.AddDirEdge(id, k, next_id, k, cost);
                }
                if(k == Down && i < H - 1 && C[i + 1][j] == '.') {
                    int next_id = pi.GetId(i + 1, j);
                    dk.AddDirEdge(id, k, next_id, k, cost);
                }
                if(k == Left && j > 0 && C[i][j - 1] == '.') {
                    int next_id = pi.GetId(i, j - 1);
                    dk.AddDirEdge(id, k, next_id, k, cost);
                }
                if(k == Right && j < W - 1 && C[i][j + 1] == '.') {
                    int next_id = pi.GetId(i, j + 1);
                    dk.AddDirEdge(id, k, next_id, k, cost);
                }
            }
        }
    }

    dk.Calc(pi.GetId(X1, Y1), Center);
    //REP(i, H) {
    //    REP(j, W) {
    //        auto dist = dk.GetDist(pi.GetId(i, j), Center);
    //        if(dist.first >= LLINF) {
    //            DBG("-1.-1 ");
    //        }
    //        else {
    //            DBG("%2lld.%2lld ", dist.first, dist.second);
    //        }
    //    }
    //    DBG("\n");
    //}
    int ans = dk.GetDist(pi.GetId(X2, Y2), Center).first;
    if(ans >= LLINF) { print(-1); }
    else { print(ans); }

    return 0;
}


Measured memory_bytes: 534048