Problem:
Score : 700 points

Problem Statement

Takahashi is locked within a building.

This building consists of H×W rooms, arranged in H rows and W columns.
We will denote the room at the i-th row and j-th column as (i,j). The state of this room is represented by a character A_{i,j}. If A_{i,j}= #, the room is locked and cannot be entered; if A_{i,j}= ., the room is not locked and can be freely entered.
Takahashi is currently at the room where A_{i,j}= S, which can also be freely entered.

Each room in the 1-st row, 1-st column, H-th row or W-th column, has an exit.
Each of the other rooms (i,j) is connected to four rooms: (i-1,j), (i+1,j), (i,j-1) and (i,j+1).

Takahashi will use his magic to get out of the building. In one cast, he can do the following:

Move to an adjacent room at most K times, possibly zero. Here, locked rooms cannot be entered.

Then, select and unlock at most K locked rooms, possibly zero. Those rooms will remain unlocked from then on.

His objective is to reach a room with an exit. Find the minimum necessary number of casts to do so.

It is guaranteed that Takahashi is initially at a room without an exit.

Constraints

3 ≤ H ≤ 800

3 ≤ W ≤ 800

1 ≤ K ≤ H×W

Each A_{i,j} is # , . or S.

There uniquely exists (i,j) such that A_{i,j}= S, and it satisfies 2 ≤ i ≤ H-1 and 2 ≤ j ≤ W-1.

Input

Input is given from Standard Input in the following format:

H W K
A_{1,1}A_{1,2}...A_{1,W}
:
A_{H,1}A_{H,2}...A_{H,W}

Output

Print the minimum necessary number of casts.

Sample Input 1

3 3 3
#.#
#S.
###

Sample Output 1

1

Takahashi can move to room (1,2) in one cast.

Sample Input 2

3 3 3
###
#S#
###

Sample Output 2

2

Takahashi cannot move in the first cast, but can unlock room (1,2).
Then, he can move to room (1,2) in the next cast, achieving the objective in two casts.

Sample Input 3

7 7 2
#######
#######
##...##
###S###
##.#.##
###.###
#######

Sample Output 3

2

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

class Program
{
    public void Proc()
    {
        Reader.IsDebug = false;
        int[] inpt = Reader.ReadLine().Split(' ').Select(a => int.Parse(a)).ToArray();
        this.Height = inpt[0];
        this.Width = inpt[1];
        this.Map = new char[this.Height, this.Width];
        int move = inpt[2];
        for (int i = 0; i < this.Height; i++)
        {
            string tmp = Reader.ReadLine();
            for (int j = 0; j < this.Width; j++)
            {
                this.Map[i, j] = tmp[j];
                if (tmp[j] == 'S')
                {
                    this.StartRow = i;
                    this.StartCol = j;
                }
            }
        }
        int ans = 900;
        ans = Math.Min(ans, GetAns(StartRow, StartCol, move, MoveTo.All));

        // 1回でいけるケース
        Queue<int[]> que = new Queue<int[]>();
        que.Enqueue(new int[] { this.StartRow, StartCol });
        int[,] cnt = new int[this.Height, this.Width];
        cnt[this.StartRow, StartCol] = -1;
        while (que.Count > 0)
        {
            int[] pos = que.Dequeue();
            if (pos[0] <= 0 || pos[0] >= this.Height - 1 || pos[1] <= 0 || pos[1] >= this.Width - 1)
            {
                if (cnt[pos[0],pos[1]] <= move)
                {
                    ans = 1;
                    break;
                }
                continue;
            }
            int nextStep = Math.Max(cnt[pos[0], pos[1]], 0) + 1;
            if (pos[0] > 0 && this.Map[pos[0]-1, pos[1]] != '#')
            {
                if (cnt[pos[0] - 1, pos[1]] > nextStep || cnt[pos[0] - 1, pos[1]] == 0)
                {
                    cnt[pos[0] - 1, pos[1]] = nextStep;
                    que.Enqueue(new int[] { pos[0] - 1, pos[1] });
                }
            }

            if (pos[0] < this.Height-1 && this.Map[pos[0] + 1, pos[1]] != '#')
            {
                if (cnt[pos[0] + 1, pos[1]] > nextStep || cnt[pos[0] + 1, pos[1]] == 0)
                {
                    cnt[pos[0] + 1, pos[1]] = nextStep;
                    que.Enqueue(new int[] { pos[0] + 1, pos[1] });
                }
            }
            if (pos[1] > 0 && this.Map[pos[0], pos[1]-1] != '#')
            {
                if (cnt[pos[0], pos[1] - 1] > nextStep || cnt[pos[0], pos[1] - 1] == 0)
                {
                    cnt[pos[0], pos[1] - 1] = nextStep;
                    que.Enqueue(new int[] { pos[0], pos[1] - 1 });
                }
            }
            if (pos[1] < this.Width-1 && this.Map[pos[0], pos[1] + 1] != '#')
            {
                if (cnt[pos[0], pos[1] + 1] > nextStep || cnt[pos[0], pos[1] + 1]==0)
                {
                    cnt[pos[0], pos[1] + 1] = nextStep;
                    que.Enqueue(new int[] { pos[0], pos[1] - 1 });
                }
            }

        }
        for (int i = 0; i < this.Height; i++)
        {
            for (int j = 0; j < this.Width; j++)
            {
                if (cnt[i, j] == 0 || cnt[i, j] > move)
                {
                    continue;
                }
                MoveTo mtR = MoveTo.Down;
                int remainRow = this.Height - 1 - i;
                if (i <= remainRow)
                {
                    mtR = MoveTo.Up;
                    remainRow = i;
                }
                MoveTo mtC = MoveTo.Right;
                int remainCol = this.Width - 1 - j;
                if (j <= remainCol)
                {
                    remainCol = j;
                }
                if (remainRow <= remainCol)
                {
                    ans = Math.Min(ans, this.Move(i, j, move, mtR) + 1);
                }
                else
                {
                    ans = Math.Min(ans, this.Move(i, j, move, mtC) + 1);
                }
            }
        }
        Console.WriteLine(ans);
    }

    private enum MoveTo
    {
        All,
        Up,
        Down,
        Left,
        Right
    }

    private Dictionary<int, Dictionary<int, int>> dic = new Dictionary<int, Dictionary<int, int>>();
    private int Move(int row, int col, int move, MoveTo mt)
    {
        if (row <= 0 || row >= this.Height - 1 || col <= 0 || col >= this.Width - 1)
        {
            return 0;
        }
        int ans = 0;
        int remain = 0;
        if (mt == MoveTo.Up || mt == MoveTo.Down)
        {
            remain = row;
            if (mt == MoveTo.Down)
            {
                remain = this.Height - 1 - row;
            }
        }
        else
        {
            remain = col;
            if (mt == MoveTo.Right)
            {
                remain = this.Width - 1 - col;
            }
        }
        ans = remain / move;
        if (remain % move > 0)
        {
            ans++;
        }
        return ans;
    }
    private int GetAns(int row, int col, int move, MoveTo mt)
    {
        int ret = Math.Max(this.Width, this.Height) + 1;
        if (mt == MoveTo.All || mt == MoveTo.Up)
        {
            if (this.Map[row - 1, col] == '#')
            {
                ret = Math.Min(this.Move(row, col, move, MoveTo.Up) + 1, ret);
            }
            else
            {
                int newRow = row;
                for (int i = row; i >= 0; i--)
                {
                    if (this.Map[i, col] == '#')
                    {
                        break;
                    }
                    newRow = i;
                }
                ret = Math.Min(this.Move(newRow, col, move, MoveTo.Up) + 1, ret);
            }

        }
        if (mt == MoveTo.Down || mt == MoveTo.All)
        {
            if (this.Map[row + 1, col] == '#')
            {
                ret = Math.Min(this.Move(row, col, move, MoveTo.Down) + 1, ret);
            }
            else
            {
                int newRow = row;
                for (int i = row; i < this.Height; i++)
                {
                    if (this.Map[i, col] == '#')
                    {
                        break;
                    }
                    newRow = i;
                }
                ret = Math.Min(this.Move(newRow, col, move, MoveTo.Down) + 1, ret);
            }

        }
        if (mt == MoveTo.All || mt == MoveTo.Left)
        {
            if (this.Map[row, col-1] == '#')
            {
                ret = Math.Min(this.Move(row, col, move, MoveTo.Left) + 1, ret);
            }
            else
            {
                int newCol = col;
                for (int i = col; i >= 0; i--)
                {
                    if (this.Map[row, i] == '#')
                    {
                        break;
                    }
                    newCol = i;
                }
                ret = Math.Min(this.Move(row, newCol, move, MoveTo.Left) + 1, ret);
            }

        }
        if (mt == MoveTo.All || mt == MoveTo.Right)
        {
            if (this.Map[row, col + 1] == '#')
            {
                ret = Math.Min(this.Move(row, col, move, MoveTo.Right) + 1, ret);
            }
            else
            {
                int newCol = col;
                for (int i = col; i <this.Width; i++)
                {
                    if (this.Map[row, i] == '#')
                    {
                        break;
                    }
                    newCol = i;
                }
                ret = Math.Min(this.Move(row, newCol, move, MoveTo.Right) + 1, ret);
            }

        }
        return ret;
    }

    private int StartRow = 0;
    private int StartCol = 0;

    private int Width = 0;
    private int Height = 0;

    private char[,] Map;

    public class Reader
    {
        public static bool IsDebug = true;
        private static String PlainInput = @"


3 3 3
#.#
#S.
###


";
        private static System.IO.StringReader Sr = null;
        public static string ReadLine()
        {
            if (IsDebug)
            {
                if (Sr == null)
                {
                    Sr = new System.IO.StringReader(PlainInput.Trim());
                }
                return Sr.ReadLine();
            }
            else
            {
                return Console.ReadLine();
            }
        }
    }
    static void Main()
    {
        Program prg = new Program();
        prg.Proc();
    }
}