module WeightedDirectedGraph
  (* 辺の重み *)
  (Weight : sig
    type t
    val zero : t
    val compare : t -> t -> int
  end)
  (* 経路長を優先度としたヒープの実装 *)
  (Heap : sig
    type t
    type elt (* 頂点に相当 *)
    type key = Weight.t (* 経路長に相当 *)
    (* ヒープが空ならNoneを，
       そうでなければ経路長が最小となるbindingを一つ以上返す
       返したbindingは全てヒープから削除される *)
    val take_min_bindings : t -> (key * elt list) option
    (* ヒープにbindingを追加する
       既に同じ頂点についてのbindingが追加されていたら，
       経路長の短い方だけを残しても良いし，何も考えずに追加してもよい．
       前者の実装ならダイクストラ法の実装が時間計算量O((V + E) log V)，
       空間計算量O(V)に改善する *)
    val add : t -> key -> elt -> unit
  end)
  (* 頂点を添字，経路長を要素とした配列の実装 *)
  (Array : sig
    type t
    type key = Heap.elt
    type elt = Heap.key
    val get : t -> key -> elt
    val set : t -> key -> elt -> unit
  end)
: sig
  type weight = Array.elt
  type vertex = Array.key

  (* ダイクストラ法で最短経路を求める関数 *)
  val shortest_path :
    (* 空なヒープ *)
    Heap.t ->
    (* 全ての頂点についての経路長が無限大で初期化された配列
       Array.getした時に極端に大きな経路長が返ってくる実装でも良いし，
       Not_foundが投げられる実装でも良い *)
    Array.t ->
    (* 最短経路を求めたいグラフの，ある頂点から伸びる辺に対してのイテレータ *)
    (vertex -> (vertex -> (weight -> weight) (* 辺を通った際のコストを加算する関数 *) -> unit) -> unit) ->
    (* 始点 *)
    vertex ->
    (* 終点を受け取って，始点からの最短距離を返す関数
       始点から辿り着けない場合，無限大を返すかNot_foundを投げる（Arrayの実装依存）
       この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
    (vertex -> weight)
end
= struct
  type weight = Array.elt
  type vertex = Array.key

  let shortest_path q d es s =
    (* 始点への経路長を0にする *)
    Array.set d s Weight.zero;
    (* 既に最短距離が確定した辺へのクエリを高速化するため，
       ヒープの最小要素をメモしておく *)
    let min_bindings = ref (Some (Weight.zero, [s])) in
    let rec dijkstra t =
      match !min_bindings with
      (* もう既に全ての頂点までの距離が分かっている *)
      | None -> Array.get d t
      | Some (w, us) ->
          match Array.get d t with
          (* 既に終点までの距離が分かっているので返す *)
          | x when 0 <= Weight.compare w x -> x
          (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
          | _ | exception Not_found ->
              List.iter (fun u ->
                (* 未だ頂点uを訪れていない *)
                if 0 <= Weight.compare (Array.get d u) w then
                  es u @@ fun v f ->
                    (* uからvに伸びる辺を通った際の経路長 *)
                    let c = f w in
                    if 0 < Weight.compare (Array.get d v) c then
                      (Heap.add q c v; Array.set d v c)) us;
              min_bindings := Heap.take_min_bindings q;
              dijkstra t in
    dijkstra
end

module Int = struct
  type t = int
  let zero = 0
  let compare = compare
end

module IntMap = Map.Make (Int)

module G = WeightedDirectedGraph (Int)
  (struct
    type t = int array list IntMap.t ref
    type key = int
    type elt = int array
    let take_min_bindings q =
      match IntMap.min_binding !q with
      | exception Not_found -> None
      | (w, _) as p -> q := IntMap.remove w !q; Some p
    let add q w v  =
      q := IntMap.update w (fun vs -> Some (v :: Option.value ~default:[] vs)) !q
  end)
  (struct
    type t = (int, Bigarray.int_elt, Bigarray.c_layout) Bigarray.Genarray.t
    type elt = int
    type key = int array
    let get = Bigarray.Genarray.get
    let set = Bigarray.Genarray.set
  end)

let () = Scanf.scanf "%d %d %d\n%d %d %d %d\n" @@ fun h w k x1 y1 x2 y2 ->
  let css = Array.init h @@ fun _ -> Scanf.scanf "%s\n" Fun.id in
  let dx = [| 1; 0; -1; 0 |] in
  let dy = [| 0; 1; 0; -1 |] in
  let d = G.shortest_path (ref IntMap.empty)
    (let d = Bigarray.Genarray.create Bigarray.int Bigarray.c_layout [| h; w; 4 |] in Bigarray.Genarray.fill d max_int; d)
    (fun [| i; j; dir |] f ->
      f [| i; j; (dir + 1) mod 4 |] (fun c -> c + k - 1 - (c + k - 1) mod k);
      let i = i + dx.(dir) in
      let j = j + dy.(dir) in
      if 0 <= i && i < h && 0 <= j && j < w && css.(i).[j] <> '@' then
        f [| i; j; dir |] succ)
    [| x1 - 1; y1 - 1; 0 |] in
  Printf.printf "%d\n" @@
  (fun x -> if max_int <= x then -1 else (x + k - 1) / k) @@
  Array.fold_left min max_int @@
  Array.init 4 @@ fun dir -> d [| x2 - 1; y2 - 1; dir |]


Measured memory_bytes: 59376