#include <iostream>
#include <algorithm>
#include <exception>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
using namespace std;
using int_pair = pair<int, int>;
#define SIZE 1000
#define y first
#define x second
// 윗층 뒤 우 아래층 잎 좌
pair<int, int_pair> arr_pos[]
{
{1, {0, 0}},
{0, {-1, 0}},
{0, {0, 1}},
{-1, {0, 0}},
{0, {1, 0}},
{0, {0, -1}}
};
vector<vector<vector<int>>> graph;
// w:넓이, h:높이, l:층수
int w, h, l;
queue<pair<int,int_pair>> q;
void BFS()
{
#define ARR_POS_SIZE 6
while (!q.empty())
{
auto front = q.front(); q.pop();
//cout << front.y << front.x.y << front.x.x << endl;
for (int i = 0; i < ARR_POS_SIZE; i++)
{
auto first = front.x.y, second = front.x.x;
auto nz = front.y + arr_pos[i].y; // 다음 층
int ny = first + arr_pos[i].x.y; // 다음 앞 뒤
int nx = second + arr_pos[i].x.x; // 다음 좌 우
// 범위 체크
if (nx < 0 ||
nx >= w ||
ny < 0 ||
ny >= h ||
nz < 0 ||
nz >= l)
continue;
// 토마토가 존재
if (graph[nz][ny][nx] == 0)
{
q.push({ nz, { ny,nx} });
graph[nz][ny][nx] = graph[front.y][first][second] + 1;
}
}
}
}
int main()
{
cin >> w >> h >> l;
// 그래프 입력
graph.resize(l);
for (int i = 0; i < l; i++)
{
graph[i].resize(h);
for (int y = 0; y < h; y++)
{
graph[i][y].resize(w);
for (int x = 0; x < graph[i][y].size(); x++)
{
cin >> graph[i][y][x];
if (graph[i][y][x] == 1)
q.push({ i, { y,x } });
}
}
}
BFS();
int result = 0;
for (int i = 0; i < l; i++)
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
// 익지않은 토마토가 존재할 경우
if (graph[i][y][x] == 0)
{
cout << -1;
return 0;
}
// 익은 토마토일 시
result = max(result, graph[i][y][x]);
}
}
}
cout << result - 1;
return 0;
}