#include <bits/stdc++.h>
// #include <boost/multiprecision/cpp_int.hpp>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *std::min_element((a).begin(), (a).end())
#define MAX(a) *std::max_element((a).begin(), (a).end())
#define SUM(a) std::accumulate((a).begin(), (a).end(), 0LL)
#define REP(i, n) for (std::size_t (i) = 0; (i) < (n); (i)++)
#define RREP(i, n) for (std::size_t (i) = (n)-1; (i) >= 0; (i)--)
#define FOR(i, m, n) for (std::size_t (i) = (m); (i) < (n); i++)
#define FORR(i, m, n) for (std::size_t (i) = (n)-1; (i) >= (m); i--)
#define debug(x) std::cerr << #x << " = " << x << '\n'
// #define int long long

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vl = std::vector<long long>;
using vvl = std::vector<std::vector<long long>>;
// using bint = boost::multiprecision::cpp_int;
// using rat = boost::rational<bint>;

constexpr int inf = (1 << 30) - 1;
constexpr long long INF = 1LL << 60;

inline void ios_() {std::cin.tie(nullptr); std::ios::sync_with_stdio(false);}
template<typename T> inline T Div(const T& a, const T& b) {return (a + b - 1) / b;}
template<typename T> bool chmin(T& a, const T& b) {if(a > b){a = b; return true;} return false;}
template<typename T> bool chmax(T& a, const T& b) {if(a < b){a = b; return true;} return false;}

template<typename T>
inline void finish(const T& msg) {
    std::cout << msg << std::endl;
    std::exit(0);
}

template<typename T>
long long binarySearch(long long ng, long long ok, const T& fn) {
    while (std::abs(ok - ng) > 1) {
        T mid = (ok + ng) / 2;
        if (fn(mid)) ok = mid;
        else ng = mid;
    }
    return ok;
}

struct ModInt {
    long long value;
    static const long long mod; // mod must be a prime number

    ModInt(long long v = 0) : value(((v % mod) + mod) % mod) {}

    ModInt pow(long long n) const {
        long long x = value, res = 1;
        while(n > 0) {
            if(n & 1) {
                res = res * x % mod;
            }
            x = x * x % mod;
            n >>= 1;
        }
        return ModInt(res);
    }

    ModInt inverse() const {
        return pow(mod - 2);
    }

    ModInt operator-() const {
        return ModInt((mod - value) % mod);
    }

    ModInt& operator+=(const ModInt& a) {
        value += a.value;
        value %= mod;
        return *this;
    }

    ModInt& operator-=(const ModInt& a) {
        value += (-a).value;
        value %= mod;
        return *this;
    }

    ModInt& operator*=(const ModInt& a) {
        value *= a.value;
        value %= mod;
        return *this;
    }

    ModInt& operator/=(const ModInt& a) {
        return (*this) *= a.inverse();
    }

    ModInt operator+(const ModInt& a) const {
        return ModInt(*this) += a;
    }

    ModInt operator-(const ModInt& a) const {
        return ModInt(*this) -= a;
    }

    ModInt operator*(const ModInt& a) const {
        return ModInt(*this) *= a;
    }

    ModInt operator/(const ModInt& a) const {
        return ModInt(*this) /= a;
    }

    bool operator==(const ModInt& a) const {
        return value == a.value;
    }

    bool operator!=(const ModInt& a) const {
        return value != a.value;
    }

    friend std::istream& operator>>(std::istream& is, ModInt& a) {
        long long v;
        is >> v;
        a = v;
        return is;
    }

    friend std::ostream& operator<<(std::ostream& os, const ModInt& a) {
        os << a.value;
        return os;
    }

    static ModInt factorial(int n) {
        static std::vector<ModInt> fact(1 << 18);
        if(fact.size() <= n) {
            fact.resize(n + 1);
        }
        if(n < 0) {
            return 0;
        }
        if(n == 0) {
            return 1;
        }
        if(fact[n] != 0) {
            return fact[n];
        }
        return fact[n] = factorial(n - 1) * n;
    }

    static ModInt combin(int n, int k) {
        if(n < 0 || k < 0 || n < k) {
            return 0;
        }
        return factorial(n) / (factorial(k) * factorial(n - k));
    }
};
const long long ModInt::mod = 1e9+7;
// const long long ModInt::mod = 998244353;
using mint = ModInt;

#include <vector>
#include <deque>
#include <queue>
#include <algorithm>
using ll = long long;

struct Graph {
    struct Edge {
        int from;
        int to;
        ll cost;
        int dx, dy;
        Edge(int a, ll b) : to(a), cost(b) {}
        Edge(int a, int b, ll c) : from(a), to(b), cost(c) {}
        Edge(int a, int b ,ll c, int x, int y) : from(a), to(b), cost(c), dx(x), dy(y) {}
    };

    int N;  //頂点数
    std::vector<std::vector<Edge>> edges;   //隣接リスト
    std::vector<ll> dist;   //ノードの深さ
    std::vector<int> deg;   //入次数

    Graph(int n) : N(n), edges(n), dist(n, INF), deg(n, 0) {}

    void connect(int a, int b, ll c) {   //辺を追加
        edges[a].emplace_back(Edge(a, b, c));
        deg[b]++;
    }

    bool visited(int v) {
        return dist[v] < INF;
    }

    void resetDist() {
        for(int i=0; i<N; i++) {
            dist[i] = INF;
        }
    }

    void dfs(int p, int v, ll d) {    //深さ優先探索
        if(visited(v)) return;

        dist[v] = d;

        for(const Edge& e : edges[v]) {
            if(e.to == p) continue;
            dfs(v, e.to, d + e.cost);
        }
    }

    void bfs(int v) {        //幅優先探索
        std::queue<Edge> que;
        for(const Edge& e : edges[v]) {
            que.push(e);
            dist[e.to] = e.cost;
        }

        dist[v] = 0;

        while(!que.empty()) {
            int u = que.front().to;
            ll d = que.front().cost;
            que.pop();

            for(const Edge& e : edges[u]) {
                if(!visited(e.to)) {
                    que.push(Edge(e.from, e.to, d + e.cost));
                    dist[e.to] = d + e.cost;
                }
            }
        }
    }

    ll diameter() {  //木の直径を求める
        static ll res = INF;
        if(res != INF) return res;  //計算済みの場合

        dfs(-1, 0, 0);  //頂点0からの最遠頂点vを求める
        int v = std::max_element(dist.begin(), dist.end()) - dist.begin();

        resetDist();

        dfs(-1, v, 0);  //vからの最遠頂点を求める

        return res = *std::max_element(dist.begin(), dist.end());   //この2頂点間の距離が直径
    }

    void dijkstra(int start) {   //ダイクストラ法
        dist[start] = 0;

        auto fn = [](const Edge& a, const Edge& b){return a.cost > b.cost;};
        std::priority_queue<Edge, std::vector<Edge>, decltype(fn)> que(fn);

        for(const Edge& e : edges[start]) que.push(e);

        while(!que.empty()) {
            auto v = que.top().to;
            auto d = que.top().cost;
            que.pop();

            if(visited(v)) continue;
            else dist[v] = d;
            
            for(const Edge& e : edges[v]) {
                if(dist[e.to] == INF) {
                    que.push(Edge(e.from, e.to, e.cost + d));
                }
            }
        }
    }
};

struct MatrixGraph : Graph {
    MatrixGraph(int n) : Graph(n) {
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                edges[i].emplace_back(Edge(i, j, (i == j ? 0 : INF)));
            }
        }
    }

    void connect(int a, int b, ll c) {
        edges[a][b].cost = c;
    }

    void WarshallFloyd() {
        for(int k = 0; k < N; k++) {
            for(int i = 0; i < N; i++) {
                for(int j = 0; j < N; j++) {
                    ll d = edges[i][k].cost + edges[k][j].cost;
                    if(d < edges[i][j].cost) {
                        edges[i][j].cost = d;
                    }
                }
            }
        }
    }
};

struct GridGraph : Graph {
    int H, W;
    std::vector<std::vector<bool>> grid;
    std::vector<int> dx, dy;
    int K;

    GridGraph(int h, int w) : Graph(h*w), H(h), W(w), grid(h, std::vector<bool>(w, false)) {
        dx = {1, 0, -1, 0, 1, 1, -1, -1};
        dy = {0, 1, 0, -1, 1, -1, 1, -1};
    }

    void setGrid(int x, int y, bool b) {
        grid[x][y] = b;
    }

    bool out(int x, int y) {
        return (x < 0 || x >= H || y < 0 || y >= W);
    }

    int to1D(int x, int y) {
        return x * W + y;
    }

    int getx(int i) {
        return i / W;
    }

    int gety(int i) {
        return i % W;
    }

    void connectAll(bool diagonal) {
        for(int x = 0; x < H; x++) {
            for(int y = 0; y < W; y++) {
                if(!grid[x][y]) continue;

                for(int k = 0; k < (diagonal ? 8 : 4); k++) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if(out(nx, ny) || !grid[nx][ny]) continue;
                    connect(to1D(x, y), to1D(nx, ny), 1);
                }
            }
        }
    }

    void bfs(int v) {        //幅優先探索
        queue<Edge> que;
        que.push(Edge(-1, v, 0));
        dist[v] = 0;

        while(!que.empty()){
            auto e = que.front();
            int u = e.to;
            ll d = e.cost;
            que.pop();

            REP(i, 4){
                int x = getx(u), y = gety(u);
                int ddx = 0, ddy = 0;

                REP(j, K){
                    ddx += dx[i];
                    ddy += dy[i];
                    if(out(x + ddx, y + ddy) || !grid[x + ddx][y + ddy]) break;
                    int next = to1D(x + ddx, y + ddy);
                    if(dist[u] >= dist[next]) break;
                    if(visited(next)) continue;
                    que.push(Edge(u, next, d + 1));
                    chmin(dist[next], d + 1);
                    
                }
            }
        }
    }
};


signed main() {
    int h, w, k;
    cin >> h >> w >> k;
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    x1--; y1--; x2--; y2--;

    GridGraph G(h, w);

    REP(i, h){
        REP(j, w){
            char c;
            cin >> c;
            G.setGrid(i, j, (c == '.'));
        }
    }

    G.K = k;

    G.bfs(G.to1D(x1, y1));

    ll ans = G.dist[G.to1D(x2, y2)];
    cout << (ans < INF ? ans : -1) << endl;

    return 0;
}


Measured memory_bytes: 41364