#include <bits/stdc++.h>
using namespace std;

inline void chmin(int &a, int b){a = min(a, b);}

struct MinCostFlow {
	struct Edge {
		int dst, cap, cost, rev;
		Edge(){}
		Edge(int dst, int cap, int cost, int rev): dst(dst), cap(cap), cost(cost), rev(rev){}
	};
	
	typedef std::vector<Edge> Edges;
	typedef std::vector<Edges> Graph;
	
	static const int INF = 1 << 20;
	
	MinCostFlow(){}
	MinCostFlow(int v): g(v){}
	
	void addEdge(int src, int dst, int cap, int cost)
	{
		g[src].push_back(Edge(dst, cap, cost, g[dst].size()));
		g[dst].push_back(Edge(src, 0, -cost, g[src].size() - 1));
	}
	
	int solve(int s, int t, int f)
	{	
		std::vector<int> dist(g.size()), prevv(g.size()), preve(g.size());
		
		int res = 0;
		
		while (f > 0){
			std::fill_n(dist.begin(), dist.size(), INF);
			dist[s] = 0;
			
			bool update = true;
			while (update){
				update = false;
				for (int v = 0; v < g.size(); v++){
					if (dist[v] == INF) continue;
					for (int i = 0; i < g[v].size(); i++){
						Edge &e = g[v][i];
						if (e.cap > 0 && dist[e.dst] > dist[v] + e.cost){
							dist[e.dst] = dist[v] + e.cost;
							prevv[e.dst] = v;
							preve[e.dst] = i;
							update = true;
						}
					}
				}
			}
			if (dist[t] == INF) return INF;
			int d = f;
			for (int v = t; v != s; v = prevv[v]){
				d = std::min(d, g[prevv[v]][preve[v]].cap);
			}
			f -= d;
			res += d * dist[t];
			for (int v = t; v != s; v = prevv[v]){
				Edge &e = g[prevv[v]][preve[v]];
				e.cap -= d;
				g[v][e.rev].cap += d;
			}
		}
		return res;
	}
	
private:
	Graph g;
};


const int MAX_D = 8;
const int MAX_K = 8;
const int MAX_L = 8;
const int MAX_M = 200;
const int MAX_N = 200;
const int MAX_P = 200;
const int INF = MinCostFlow::INF;

int D, K, L;
int M, N, P;
int c[MAX_D][MAX_K];
int r[MAX_M][MAX_K];
int t[MAX_P][MAX_K];

int pow3[MAX_K + 1];
int dp[MAX_D + 1][MAX_L + 1][6561]; // 3 ** 8 == 6561

int pack(int a[])
{
	int res = 0;
	for (int i = 0; i < K; i++){
		res += a[i] * pow3[i];
	}
	return res;
}

void unpack(int a, int res[])
{
	for (int i = 0; i < K; i++){
		res[i] = a % 3;
		a /= 3;
	}
}

void solve_dp()
{
	fill_n(**dp, sizeof(dp) / 4, INF);
	dp[0][0][0] = 0;
	
	for (int i = 0; i < D; i++){
		for (int j = 0; j < L; j++){
			for (int k = 0; k < pow3[K]; k++){
				int cur[8];
				unpack(k, cur);
				for (int l = 0; l < K; l++){
					if (cur[l] == 2) continue;
					int nk = k + pow3[l];
					chmin(dp[i][j + 1][nk], dp[i][j][k] + c[i][l]);
				}
			}
		}
		for (int j = 0; j <= L; j++){
			for (int k = 0; k < pow3[K]; k++){
				chmin(dp[i + 1][0][k], dp[i][j][k]);
			}
		}
	}
}


int C1[MAX_M];
int C2[MAX_M][MAX_P];
int solve_flow()
{
	for (int i = 0; i < M; i++){
		C1[i] = dp[D][0][pack(r[i])];
	}
	
	
	for (int i = 0; i < M; i++){
		for (int j = 0; j < P; j++){
			bool canuse = true;
			int tmp[MAX_K] = {};
			for (int k = 0; k < K; k++){
				tmp[k] = r[i][k] - t[j][k];
				if (tmp[k] < 0) canuse = false;
			}
			if (canuse) C2[i][j] = dp[D][0][pack(tmp)];
			else C2[i][j] = INF;
		}
	}
	
	MinCostFlow flow(P + M + 3);
	int S = P + M, T = P + M + 1, I = P + M + 2;
	
	flow.addEdge(S, I, INF, 0);
	for (int i = 0; i < P; i++){
		flow.addEdge(S, i, 1, 0);
	}
	
	for (int i = 0; i < M; i++){
		flow.addEdge(I, P + i, 1, C1[i]);
	}
	for (int i = 0; i < P; i++){
		for (int j = 0; j < M; j++){
			flow.addEdge(i, P + j, 1, C2[j][i]);
		}
	}
	
	for (int i = 0; i < M; i++){
		flow.addEdge(P + i, T, 1, 0);
	}
	
	int res = flow.solve(S, T, N);
	if (res == INF) return -1;
	else return res;
}

int solve()
{
	solve_dp();
	return solve_flow();
}

int main()
{
	pow3[0] = 1;
	for (int i = 1; i <= 8; i++){
		pow3[i] = pow3[i - 1] * 3;
	}
	
	while (scanf("%d %d %d", &D, &K, &L), D){
		for (int i = 0; i < D; i++){
			for (int j = 0; j < K; j++){
				scanf("%d", &c[i][j]);
			}
		}
		scanf("%d %d %d", &M, &N, &P);
		for (int i = 0; i < M; i++){
			for (int j = 0; j < K; j++){
				scanf("%d", &r[i][j]);
			}
		}
		for (int i = 0; i < P; i++){
			for (int j = 0; j < K; j++){
				scanf("%d", &t[i][j]);
			}
		}
		printf("%d\n", solve());
	}
}

Measured memory_bytes: 4960