#include <bits/stdc++.h>

using i32 = int_fast32_t;
using i64 = int_fast64_t;
using u32 = uint_fast32_t;
using u64 = uint_fast64_t;
using f64 = double;
using f80 = long double;

#define FOR(v, a, b) for(i64 v = (a); v < (b); ++v)
#define FORE(v, a, b) for(i64 v = (a); v <= (b); ++v)
#define REP(v, n) FOR(v, 0, n)
#define REPE(v, n) FORE(v, 0, n)
#define REV(v, a, b) for(i64 v = (a); v >= (b); --v)
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define ITR(it, c) for(auto it = (c).begin(); it != (c).end(); ++it)
#define RITR(it, c) for(auto it = (c).rbegin(); it != (c).rend(); ++it)
#define EXIST(c,x) ((c).find(x) != (c).end())
#define fst first
#define snd second
#define UNIQ(v) (v).erase(unique(ALL(v)), (v).end())
#define bit(i) (1LL<<(i))

#ifdef DEBUG
#include <Mylib/Debug/debug.cpp>
#else
#define dump(...) ((void)0)
#endif

using namespace std;

template <typename I> void join(ostream &ost, I s, I t, string d=" "){for(auto i=s; i!=t; ++i){if(i!=s)ost<<d; ost<<*i;}ost<<endl;}
template <typename T> istream& operator>>(istream &is, vector<T> &v){for(auto &a : v) is >> a; return is;}

template <typename T, typename U> bool chmin(T &a, const U &b){return (a>b ? a=b, true : false);}
template <typename T, typename U> bool chmax(T &a, const U &b){return (a<b ? a=b, true : false);}

template <typename T, size_t N, typename U> void fill_array(T (&a)[N], const U &v){fill((U*)a, (U*)(a+N), v);}
template <typename T> auto make_vector(int n, int m, const T &value){return vector<vector<T>>(n, vector<T>(m, value));}

template <typename T> void print(const T &value){std::cout << value << "\n";}
template <typename T, typename ...Args> void print(const T &value, const Args&... args){std::cout << value << " ";print(args...);}


struct Init{
  Init(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(12);
    cerr << fixed << setprecision(12);
  }
}init;

/**
 * @title Grid template
 * @docs grid.md
 */
struct Point{
  int x, y;
  Point(): x(0), y(0){}
  Point(int x, int y): x(x), y(y){}
  Point& operator+=(const Point &a){this->x += a.x; this->y += a.y; return *this;}
  Point& operator-=(const Point &a){this->x -= a.x; this->y -= a.y; return *this;}
};

Point operator+(const Point &a, const Point &b){return Point(a.x+b.x, a.y+b.y);}
Point operator-(const Point &a, const Point &b){return Point(a.x-b.x, a.y-b.y);}
bool operator==(const Point &a, const Point &b){return a.x == b.x and a.y == b.y;}
bool operator!=(const Point &a, const Point &b){return !(a == b);}

bool operator<(const Point &a, const Point &b){
  return std::make_pair(a.x, a.y) < std::make_pair(b.x, b.y);
}

std::ostream& operator<<(std::ostream &os, const Point &a){
  os << "(" << a.x << "," << a.y << ")";
  return os;
}

namespace grid{
  const auto LEFT = Point(0, -1);
  const auto RIGHT = Point(0, 1);
  const auto UP = Point(-1, 0);
  const auto DOWN = Point(1, 0);
  
  const std::array<Point, 4> dir4 = {LEFT, RIGHT, UP, DOWN};
  const std::array<Point, 8> dir8 = {LEFT, RIGHT, UP, DOWN, LEFT + UP, LEFT + DOWN, RIGHT + UP, RIGHT + DOWN};
}



int main(){
  int H, W, K;

  while(cin >> H >> W >> K){
    int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
    --x1, --y1, --x2, --y2;
    
    vector<string> s(H); cin >> s;


    auto left = make_vector<optional<int>>(H, W, {});
    REP(i,H){
      FOR(j,0,W){
        if(s[i][j] == '@') left[i][j] = 0;
        if(s[i][j] == '.' and j > 0 and left[i][j-1]) left[i][j] = *left[i][j-1] + 1;
      }
    }
    
    auto right = make_vector<optional<int>>(H, W, {});
    REP(i,H){
      REV(j,W-1,0){
        if(s[i][j] == '@') right[i][j] = 0;
        if(s[i][j] == '.' and j < W-1 and right[i][j+1]) right[i][j] = *right[i][j+1] + 1;
      }
    }
    
    auto up = make_vector<optional<int>>(H, W, {});
    REP(j,W){
      FOR(i,0,H){
        if(s[i][j] == '@') up[i][j] = 0;
        if(s[i][j] == '.' and i > 0 and up[i-1][j]) up[i][j] = *up[i-1][j] + 1;
      }
    }
    
    auto down = make_vector<optional<int>>(H, W, {});
    REP(j,W){
      REV(i,H-1,0){
        if(s[i][j] == '@') down[i][j] = 0;
        if(s[i][j] == '.' and i < H-1 and down[i+1][j]) down[i][j] = *down[i+1][j] + 1;
      }
    }
    

    queue<Point> q;
    auto dist = make_vector<i64>(H, W, INT_MAX);
    auto check = make_vector<bool>(H, W, false);

    dist[x1][y1] = 0;
    q.emplace(x1, y1);

    vector<set<int>> vert(W), hori(H);
    REP(i,H){
      REP(j,W){
        hori[i].insert(j);
        vert[j].insert(i);
      }
    }
    
    
    while(q.size()){
      auto cur = q.front(); q.pop();


      if(check[cur.x][cur.y]) continue;
      check[cur.x][cur.y] = true;

      int l, r, u, d;

      l = max(cur.y - K, 0);
      if(left[cur.x][cur.y]) l = max(l, cur.y - *left[cur.x][cur.y] + 1);

      r = min(cur.y + K, W-1);
      if(right[cur.x][cur.y]) r = min(r, cur.y + *right[cur.x][cur.y] - 1);

      u = max(cur.x - K, 0);
      if(up[cur.x][cur.y]) u = max(u, cur.x - *up[cur.x][cur.y] + 1);

      d = min(cur.x + K, H-1);
      if(down[cur.x][cur.y]) d = min(d, cur.x + *down[cur.x][cur.y] - 1);

      //dump(cur, hori[cur.x], l, r);

      while(1){
        auto it = hori[cur.x].lower_bound(l);
        if(it == hori[cur.x].end() or *it > r) break;

        if(chmin(dist[cur.x][*it], dist[cur.x][cur.y] + 1)){
          q.emplace(cur.x, *it);
        }
        
        hori[cur.x].erase(it);
      }

      while(1){
        auto it = vert[cur.y].lower_bound(u);
        if(it == vert[cur.y].end() or *it > d) break;

        if(chmin(dist[*it][cur.y], dist[cur.x][cur.y] + 1)){
          q.emplace(*it, cur.y);
        }
        
        vert[cur.y].erase(it);
      }
    }

    REP(i,H) dump(dist[i]);

    //dump(dist[x2][y2]);
    if(dist[x2][y2] == INT_MAX){
      print(-1);
    }else{
      print(dist[x2][y2]);
    }
  }
  
  return 0;
}


Measured memory_bytes: 184156