#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define zero_pad(num) setfill('0') << std::right << setw(num)
using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;

/* RMQ：[0,n-1] について、区間ごとの最小値を管理する構造体
    set(int i, T x), build(): i番目の要素をxにセット。まとめてセグ木を構築する。O(n)
    update(i,x): i 番目の要素を x に更新。O(log(n))
    query(a,b): [a,b) での最小の要素を取得。O(log(n))
    find_rightest(a,b,x): [a,b) で x以下の要素を持つ最右位置を求める。O(log(n))
    find_leftest(a,b,x): [a,b) で x以下の要素を持つ最左位置を求める。O(log(n))
*/
template <typename T>
struct RMQ {
    const T e = numeric_limits<T>::max();
    function<T(T, T)> fx = [](T x1, T x2) -> T { return min(x1, x2); };
    int n;
    vector<T> dat;
    RMQ(int n_) : n(), dat(n_ * 4, e) {
        int x = 1;
        while (n_ > x) {
            x *= 2;
        }
        n = x;
    }
    void set(int i, T x) { dat[i + n - 1] = x; }
    void build() {
        for (int k = n - 2; k >= 0; k--) dat[k] = fx(dat[2 * k + 1], dat[2 * k + 2]);
    }
    void update(int i, T x) {
        i += n - 1;
        dat[i] = x;
        while (i > 0) {
            i = (i - 1) / 2;  // parent
            dat[i] = fx(dat[i * 2 + 1], dat[i * 2 + 2]);
        }
    }
    // the minimum element of [a,b)
    T query(int a, int b) { return query_sub(a, b, 0, 0, n); }
    T query_sub(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) {
            return e;
        } else if (a <= l && r <= b) {
            return dat[k];
        } else {
            T vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
            T vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
            return fx(vl, vr);
        }
    }
    int find_rightest(int a, int b, T x) { return find_rightest_sub(a, b, x, 0, 0, n); }
    int find_leftest(int a, int b, T x) { return find_leftest_sub(a, b, x, 0, 0, n); }
    int find_rightest_sub(int a, int b, T x, int k, int l, int r) {
        if (dat[k] > x || r <= a || b <= l) {  // 自分の値がxより大きい or [a,b)が[l,r)の範囲外ならreturn a-1
            return a - 1;
        } else if (k >= n - 1) {  // 自分が葉ならその位置をreturn
            return (k - (n - 1));
        } else {
            int vr = find_rightest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r);
            if (vr != a - 1) {  // 右の部分木を見て a-1 以外ならreturn
                return vr;
            } else {  // 左の部分木を見て値をreturn
                return find_rightest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2);
            }
        }
    }
    int find_leftest_sub(int a, int b, T x, int k, int l, int r) {
        if (dat[k] > x || r <= a || b <= l) {  // 自分の値がxより大きい or [a,b)が[l,r)の範囲外ならreturn b
            return b;
        } else if (k >= n - 1) {  // 自分が葉ならその位置をreturn
            return (k - (n - 1));
        } else {
            int vl = find_leftest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2);
            if (vl != b) {  // 左の部分木を見て b 以外ならreturn
                return vl;
            } else {  // 右の部分木を見て値をreturn
                return find_leftest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r);
            }
        }
    }
};

vector<int> dy = {-1, 0, 1, 0};
vector<int> dx = {0, -1, 0, 1};

int main() {
    int h, w, k;
    cin >> h >> w >> k;
    int sx, sy, gx, gy;
    cin >> sx >> sy >> gx >> gy;
    sx--; sy--; gx--; gy--;
    vector<string> s(h);
    rep(i, h)cin >> s[i];

    int INF = 1001001001;
    vector<vector<int>> d(h, vector<int>(w, INF));
    d[sx][sy] = 0;

    vector<RMQ<int>> col, row;
    RMQ<int> colr(h), rowr(w);
    rep(i, h)colr.set(i, 0);
    rep(i, w)rowr.set(i, 0);
    colr.build();
    rowr.build();
    rep(i, w)col.push_back(colr);
    rep(i, h)row.push_back(rowr);

    queue<P> que;
    que.push(make_pair(sx, sy));
    row[sx].update(sy, 1);
    col[sy].update(sx, 1);
    while(!que.empty()){
        P p = que.front();
        que.pop();
        int y = p.first;
        int x = p.second;
        if(y > 0){
            int right = col[x].find_rightest(0, y, 0);
            for(int i = right; i >= max(0, y-k); i--){
                if(s[i][x] == '@')break;
                if(d[i][x] < d[y][x] + 1)continue;
                col[x].update(i, 1);
                row[i].update(x, 1);
                d[i][x] = d[y][x] + 1;
                que.push(make_pair(i, x));
            }
        }
        if(y < h-1){
            int left = col[x].find_leftest(y, h, 0);
            for(int i = left; i <= min(h-1, y+k); i++){
                if(s[i][x] == '@')break;
                if(d[i][x] < d[y][x] + 1)continue;
                col[x].update(i, 1);
                row[i].update(x, 1);
                d[i][x] = d[y][x] + 1;
                que.push(make_pair(i, x));
            }
        }
        if(x > 0){
            int right = row[y].find_rightest(0, x, 0);
            for(int i = right; i >= max(0, x-k); i--){
                if(s[y][i] == '@')break;
                if(d[y][i] < d[y][x] + 1)continue;
                row[y].update(i, 1);
                col[i].update(y, 1);
                d[y][i] = d[y][x] + 1;
                que.push(make_pair(y, i));
            }
        }
        if(x < w-1){
            int left = row[y].find_leftest(x, w, 0);
            for(int i = left; i <= min(w-1, x+k); i++){
                if(s[y][i] == '@')break;
                if(d[y][i] < d[y][x] + 1)continue;
                row[y].update(i, 1);
                col[i].update(y, 1);
                d[y][i] = d[y][x] + 1;
                que.push(make_pair(y, i));
            }
        }
    }
    
    if(d[gx][gy] == INF)cout << -1 << endl;
    else cout << d[gx][gy] << endl;
}

Measured memory_bytes: 141060