#include <iostream>
#include <cstring>
#include <vector>
#include <tuple>
using namespace std;
const int N = 200;
const int maxn = 400 + 20;
const int maxm = maxn * maxn >> 1;
const int inf = 0x3f3f3f3f;
const int ninf = 0xcfcfcfcf;
int n, m, k, len, tot, ans, S, T, head, tail, h[maxn], d[maxn], f[maxn], p[maxn], a1[N][N], a2[N][N], q[maxm];
bool vis[maxn];
struct Edge {
int to, w1, w2, nxt;
} e[maxm];
void addedge(int u, int v, int w1, int w2) {
e[tot] = { v, w1, w2, h[u] }; h[u] = tot++;
e[tot] = { u, 0, -w2, h[v] }; h[v] = tot++;
}
bool bfs() {
memset(d, 0xcf, sizeof(d));
memset(vis, 0, sizeof(vis));
head = tail = 0;
q[tail++] = S; d[S] = 0;
vis[S] = true; f[S] = inf;
while (head < tail) {
int u = q[head++]; vis[u] = false;
for (int k = h[u]; ~k; k = e[k].nxt) if (e[k].w1) {
int v = e[k].to, w = e[k].w2;
if (d[v] < d[u] + w) {
d[v] = d[u] + w; p[v] = k;
f[v] = min(f[u], e[k].w1);
if (!vis[v]) q[tail++] = v, vis[v] = true;
}
}
} return d[T] != ninf;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k >> len;
vector<tuple<int, int, int, int, int> > g(m);
memset(h, -1, sizeof(h));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> a1[i][j];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> a2[i][j];
S = (m << 1) + 5, T = S + 5;
for (int i = 1; i <= m; i++) {
auto [a, b, s, t, c] = g[i - 1];
int u = (i - 1) << 1 | 1, v = i << 1;
addedge(u, v, 1, c);
if (t + a1[b][0] <= len) {
addedge(v, T, inf, -a2[b][0]);
if (a1[0][a] <= s)
addedge(S + 1, u, inf, -a2[0][a]);
for (int j = 0; j < m; j++)
if (t + a1[b][get<0>(g[j])] <= get<2>(g[j]))
addedge(v, j << 1 | 1, inf, -a2[b][get<0>(g[j])]);
}
}
addedge(S, S + 1, k, 0);
while (bfs()) {
for (int x = T; x != S; ) {
int k = p[x];
e[k].w1 -= f[T]; e[k ^ 1].w1 += f[T];
x = e[k ^ 1].to;
} ans += d[T] * f[T];
} cout << ans << '\n';
return 0;
}