#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
#include "bits/stdc++.h"
using namespace std;
#define pb push_back
#define F first
#define S second
#define f(i, a, b) for(int i = a; i < b; i++)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define sz(x) (int)(x).size()
#define mp(x, y) make_pair(x,y)
#define popCnt(x) (__builtin_popcountll(x))
#define int ll
using ll = long long;
using ii = pair<int, int>;
using ull = unsigned long long;
const int N = 5e5 + 5, LG = 18, MOD = 1e9 + 7;
const long double PI = acos(-1);
const long double EPS = 1e-7;
#define rep(aa, bb, cc) for(int aa = bb; aa < cc;aa++)
struct Dinic {
struct Edge {
int to, rev;
ll c, oc;
ll flow() { return max(oc - c, 0LL); } // if you need flows
};
vi lvl, ptr, q;
vector<vector<Edge>> adj;
Dinic(int n) : lvl(n), ptr(n), q(n), adj(n) {}
void addEdge(int a, int b, ll c, ll rcap = 0) {
adj[a].push_back({b, (int)adj[b].size(), c, c});
adj[b].push_back({a, (int)adj[a].size() - 1, rcap, rcap});
}
ll dfs(int v, int t, ll f) {
if (v == t || !f) return f;
for (int& i = ptr[v]; i < (int)adj[v].size(); i++) {
Edge& e = adj[v][i];
if (lvl[e.to] == lvl[v] + 1)
if (ll p = dfs(e.to, t, min(f, e.c))) {
e.c -= p, adj[e.to][e.rev].c += p;
return p;
}
}
return 0;
}
ll calc(int s, int t) {
ll flow = 0; q[0] = s;
rep(L,0,31) do { // 'int L=30' maybe faster for random data
lvl = ptr = vi((int)q.size());
int qi = 0, qe = lvl[s] = 1;
while (qi < qe && !lvl[t]) {
int v = q[qi++];
for (Edge e : adj[v])
if (!lvl[e.to] && e.c >> (30 - L))
q[qe++] = e.to, lvl[e.to] = lvl[v] + 1;
}
while (ll p = dfs(s, t, LLONG_MAX)) flow += p;
} while (lvl[t]);
return flow;
}
bool leftOfMinCut(int a) { return lvl[a] != 0; }
};
int n, m, t;
char grid[22][22];
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int getId(int i, int j, int t, bool o) {
int val = n * m * t;
val += i * m + j;
return val * 2 + o;
}
void doWork() {
cin >> n >> m >> t;
f(i, 0, n)f(j, 0, m) cin >> grid[i][j];
Dinic flw(n * m * (t + 1) * 2 + 2);
int src = n * m * (t + 1) * 2;
int snk = n * m * (t + 1) * 2 + 1;
f(i, 0, n)f(j, 0, m) if (grid[i][j] != '#') {
if (grid[i][j] == 'P')flw.addEdge(src, getId(i, j, 0, 0), 1);
if (grid[i][j] == 'E') {
f(x, 0, t + 1)flw.addEdge(getId(i, j, x, 1), snk, 1);
}
f(x, 0, t + 1)flw.addEdge(getId(i, j, x, 0), getId(i, j, x, 1), 1);
f(x, 0, t)flw.addEdge(getId(i, j, x, 1), getId(i, j, x + 1, 0), 1);
f(k, 0, 4) {
int ni = i + dx[k];
int nj = j + dy[k];
if (ni >= 0 && nj >= 0 && ni < n && nj < m && grid[ni][nj] != '#') {
f(x, 0, t) {
flw.addEdge(getId(i, j, x, 1), getId(ni, nj, x + 1, 0), 1);
}
}
}
}
cout << flw.calc(src, snk) << '\n';
}
int32_t main() {
#ifdef ONLINE_JUDGE
ios_base::sync_with_stdio(0);
cin.tie(0);
#endif // ONLINE_JUDGE
int t = 1;
// cin >> t;
while (t--) {
doWork();
}
}