#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>//万能开头
using namespace std;
const int N=1010;
int n,m,k;
int ax,ay,bx,by;
char temp[N][N];
int dis[N][N];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};//差不多DFS必备了吧
int main()
{scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++)//行scanf("%s",temp[i]+1);//因为我们每一次列都是从第一个开始存的所以加一scanf("%d%d%d%d",&ax,&ay,&bx,&by);memset(dis,-1,sizeof dis);//先初始化将所有其所有定义为-1,有的是要定义无穷,要分题而论dis[ax][ay]=0;//用过的赋值为0if(ax==bx&&ay==by)//如果起点和终点完全符合,直接输出{cout<<0;return 0;}queue<pair<int,int>> g;//这个很牛,DFS都要用,相当于吧就是可以同时同个编号存多个数的数组g.push({ax,ay});//这可不是用scanf,这个直接扔进去push进行,是以列表存储的while(g.size())//根据是否有队头来当作循环条件{auto a=g.front();//取出队头g.pop();//相当于把队头弹出去for(int i=0;i<4;i++)//循环四个方向(上,下,左,右){for(int j=1;j<=k;j++)//这个题这里是1~k步要注意!{int x=a.first+j*dx[i],y=a.second+j*dy[i];//现在要判断的位置if(temp[x][y]=='#'||x<1||x>n||y<1||y>m)break;//第一层条件,如果是个陷阱,或者超出范围直接out!if(dis[x][y]!=-1&&dis[x][y]<=dis[a.first][a.second])break;//第二层条件,相当于剪枝,为了防止超时,如果本次的点之前已经到达过,//并且效果更好(走的步数更少),就直接out!因为其他这个点的四周肯定也是之前都判断过了if(dis[x][y]!=-1)continue;//第三层条件,要看题它是不影响的(注意:注意区分本题中移动次数与移动步数的区别。)g.push({x,y});//把这个点放入队头,如果多了也只会拿第一个dis[x][y]=dis[a.first][a.second]+1;//为什么每次都加1,其实它都是在起点的基础上,//并不是累加,在1~k都是一样的,为了防止在此期间就已经到达结尾if(x==bx&&y==by)//如果到达终点就输出次数{cout<<dis[x][y];return 0;}}}}puts("-1");// cout<<-1;return 0;
}