#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 270,inf = 0x3f3f3f3f;
int n,m,k,tot;
int head[maxn],dis[maxn][maxn];
struct Edge{
int to,nxt,f;
}e[maxn*maxn];
void add(int from,int to,int f)
{
e[tot].to = to; e[tot].f = f; e[tot].nxt = head[from]; head[from] = tot++;
e[tot].to = from; e[tot].f = 0; e[tot].nxt = head[to]; head[to] = tot++;
}
void floyd()
{
for(int k = 1; k <= n+m; ++k)
for(int i = 1; i <= n+m; ++i)
for(int j = 1; j <= n+m; ++j)
dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
}
int dep[maxn];
bool bfs(int s,int t)
{
queue<int> q;
memset(dep,0,sizeof(dep));
q.push(s); dep[s] = 1;
while(!q.empty())
{
int fa = q.front(); q.pop();
for(int i = head[fa];~i;i=e[i].nxt)
{
int to = e[i].to , f = e[i].f;
if(f && !dep[to]) dep[to] = dep[fa]+1,q.push(to);
}
}
return dep[t];
}
int dfs(int v,int t,int flow)
{
if(v==t) return flow;
int sum = 0;
for(int i = head[v]; ~i; i=e[i].nxt)
{
int to = e[i].to, f = e[i].f;
if(f > 0 && dep[v] < dep[to])
{
int d = dfs(to,t,min(f,flow));
if(d > 0)
{
e[i].f -= d;
e[i^1].f += d;
flow -= d; sum+=d;
}
}
}
if(sum == 0) dep[v] = 0;
return sum;
}
int maxflow(int s,int t)
{
int ans = 0;
while(bfs(s,t)) ans+= dfs(s,t,0x3f3f3f3f);
return ans;
}
bool fun(int mid)
{
int S = 0, T = n + m + 1;
memset(head,-1,sizeof(head)); tot = 0;
for(int i = 1; i <= n; ++i) add(0,i,k);
for(int i = n + 1; i <= n + m; ++i) add(i,T,1);
for(int i = 1; i <= n; ++i)
for(int j = n + 1; j <= n + m; ++j)
if(dis[i][j] <= mid) add(i,j,1);
int ans = maxflow(S,T);
return ans == m;
}
int main()
{
//freopen("1.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(dis,0,sizeof(dis));
for(int i = 1; i <= n + m; ++i)
for(int j = 1,a; j <= n + m; ++j)
{
scanf("%d",&a);
if(i == j) dis[i][j] = 0;
else if(a == 0) dis[i][j] = inf;
else dis[i][j] = a;
}
floyd();
int l = 0, r = 10010;
while(r > l+1)
{
int mid = (l + r)/2;
if(fun(mid)) r = mid;
else l = mid;
}
printf("%d\n",r);
}
}