/*
* Problem :: 1189 / 컴백홈
*
* Kind :: DFS + Brute Force
*
* Insight
* - max(R), max(C) <= 5 이다
* 브루트 포스로 풀더라도 정말 웬만해서는 시간 제한이 걸리지 않을 정도로 작은 값이다
* # 한번 지나친 곳을 다시 방문하지 않는다니,
* DFS 로 다 돌아보면서 그때그때 방문처리 잘 해주고
* 주어진 거리가 되면 그 곳이 집인지 확인해주는 식으로 구현하면 충분할 것 같다
*
* Point
* - 방문처리시, 이전 칸으로 돌아갈 때
* 현재 칸을 방문하지 않은 칸으로 되돌려 주는 걸 잊지 말자
*
* - 거리가 실제로 이동한 거리(출발칸 포함하지 않음)가 아니라
* 거쳐간 칸의 개수(출발칸 포함)이다
* + 즉, 시작한 칸이 집이라고 하면
* 거리가 0 이 아니라 1 로 간주해야 한다
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
using namespace std;
#define endl '\n'
// Set up : Global Variables
int R, C, K;
char board[5][5];
bool isVisited[5][5];
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};
// Set up : Functions Declaration
bool isValid(int y, int x);
int dfs(int cy, int cx, int dist);
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
cin >> R >> C >> K;
for (int i=0; i<R; i++) {
for (int j=0; j<C; j++) {
cin >> board[i][j];
}
}
/* 집의 좌표를 빈칸('.')과 이동불가칸('T')으로부터 구별되는 'H'로 설정
* 집의 좌표를 전역변수 처리하기 귀찮고, 좌표끼리 비교하는 것도 귀찮아서 그렇게 함 */
board[0][C-1] = 'H';
// Process
/* DFS 돌림 */
int ans = dfs(R-1, 0, 1);
// Control : Output
cout << ans << endl;
}
// Helper Functions
bool isValid(int y, int x)
/* 주어진 좌표가 유효하면 true 를 반환, 그 외 false 를 반환 */
{
return y >= 0 && y < R && x >= 0 && x < C;
}
int dfs(int cy, int cx, int dist)
/* 현재 좌표에서 집까지 도착하는 경우중 거리가 K+1-dist 인 가짓수를 반환
* 현재 좌표 = (cy, cx), 현재 이동한 거리 = dist */
{
/* 현재 이동한 거리가 K 이면 */
if (dist == K) {
/* 현재 좌표가 집이면 1을 반환(가짓수 하나 찾음), 그렇지 않으면 0을 반환 */
return (board[cy][cx] == 'H') ? 1 : 0;
}
/* 현재 좌표 방문 처리 */
isVisited[cy][cx] = true;
int ret = 0; /* 현재 좌표에서 출발하여 집으로 가는 거리가 K+1-dist 인 가짓수 */
for (int i=0; i<4; i++) {
int ny = cy + dy[i];
int nx = cx + dx[i];
/* 좌표가 유효하고, 방문되지 않았고, 이동불가칸이 아니면 */
if (isValid(ny, nx) && not(isVisited[ny][nx]) && board[ny][nx] != 'T') {
/* 그 칸으로 이동 */
ret += dfs(ny, nx, dist+1);
}
}
/* 현재 좌표 비(非)방문 처리 */
isVisited[cy][cx] = false;
return ret;
}