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

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define INF (1<<25)
typedef int Weight;
struct Edge {
  int src, dst;
  Weight cost;
  Weight capacity;
  Edge(int src, int dst, Weight capacity=0,Weight cost=0) :
    src(src), dst(dst), cost(cost),capacity(capacity) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.cost != f.cost ? e.cost > f.cost : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

#define RESIDUE(u,v) (capacity[u][v] - flow[u][v])
#define RCOST(u,v) (cost[u][v] + h[u] - h[v])
pair<Weight, Weight> minimumCostFlow(const Graph &g, int s, int t) {
  const int n = g.size();
  Matrix capacity(n, Array(n)), cost(n, Array(n)), flow(n, Array(n));
  REP(u,n) FOR(e,g[u]) {
    capacity[e->src][e->dst] += e->capacity;
    cost[e->src][e->dst] += e->cost;
  }
  pair<Weight, Weight> total; // (cost, flow)
  vector<Weight> h(n);

  for (Weight F = INF; F > 0; ) { // residual flow
    vector<Weight> d(n, INF); d[s] = 0;
    vector<int> p(n, -1);
    priority_queue<Edge> Q; // "e < f" <=> "e.cost > f.cost"
    for (Q.push(Edge(-2, s)); !Q.empty(); ) {
      Edge e = Q.top(); Q.pop();
      if (p[e.dst] != -1) continue;
      p[e.dst] = e.src;
      FOR(f, g[e.dst]) if (RESIDUE(f->src, f->dst) > 0) {
        if (d[f->dst] > d[f->src] + RCOST(f->src, f->dst)) {
          d[f->dst] = d[f->src] + RCOST(f->src, f->dst);
          Q.push( Edge(f->src, f->dst, 0, d[f->dst]) );
        }
      }
    }
    if (p[t] == -1) break;

    Weight f = F;
    for (int u = t; u != s; u = p[u])
      f = min(f, RESIDUE(p[u], u));
    for (int u = t; u != s; u = p[u]) {
      total.first += f * cost[p[u]][u];
      flow[p[u]][u] += f; flow[u][p[u]] -= f;
    }
    F -= f;
    total.second += f;
    REP(u, n) h[u] += d[u];
  }
  return total;
}

typedef int Part;

Part zero(){
	return 0;
}

struct Condition{
	int day;
	int k;
	int l;
	int want;
};
bool operator < (const Condition &a,const Condition &b){
	if( a.day != b.day ) return a.day < b.day;
	if( a.k != b.k ) return a.k < b.k;
	if( a.l != b.l ) return a.l < b.l;
	return a.want < b.want;
}

int D,K,L;
int M,N,P;
int table[8][8];
int dp[6561][9][9][9];

int three[10] = {};
inline int get(int val,int pos){
	return val / three[pos] % 3;
}
inline int sub(int val,int pos){
	return val - three[pos];
}
int dfs(Condition c){
	if( c.l > L ) return INF;
	if( c.k == K ){
		c.day++;
		c.k = 0;
		c.l = 0;
	}
	if( c.day == D ){
		return c.want == 0 ? 0 : INF;
	}
	int &res = dp[c.want][c.day][c.k][c.l];
	if( res != -1 ) return res;
	int ans = INF;
	// no choice 
	ans = min(ans,dfs({c.day,c.k+1,c.l,c.want}));
	if( c.k < K ){
		int exCost = 0;
		Part next = c.want;
		for(int k = 0 ; k < 2 ; k++){
			if( get(next,c.k) >= 1){
				next = sub(next,c.k);
				c.l++;
				exCost += table[c.day][c.k];
				ans = min(ans,dfs({c.day,c.k+1,c.l,next})+exCost);		
			}
		}
		// two choice
	}
	return res = ans;
}

void addEdge(Graph &g,int a,int b,int cap,int cost){
	g[a].push_back(Edge(a,b,cap,cost));
	g[b].push_back(Edge(b,a,0,-cost));
}
int main(){
	three[0] = 1;
	for(int i = 1 ; i < 10 ; i++)
		three[i] = three[i-1] * 3;
	while(cin >> D >> K >> L && D){
		memset(dp,-1,sizeof(dp));
		for(int i = 0 ; i < D ; i++)
			for(int j = 0 ; j < K ; j++)
				cin >> table[i][j];
		cin >> M >> N >> P;
		vector<Part> r,p;
		
		for(int i = 0 ; i < M ; i++){
			Part t = 0;
			int wei = 1;
			for(int j = 0 ; j < K ; j++){
				int w;
				cin >> w;
				t += w * wei;
				wei *= 3;
			}
			r.push_back(t);
		}
		for(int i = 0 ; i < P ; i++){
			Part t = 0;
			int wei = 1;
			for(int j = 0 ; j < K ; j++){
				int w;
				cin >> w;
				t += w * wei;
				wei *= 3;
			}
			p.push_back(t);
		}
		int s = 0;
		int t = 1;
		Graph g(4+M+P);
		int emp = g.size() - 1;
		int veryS = g.size() - 2;
		for(int i = 0 ; i < M ; i++) addEdge(g,s,i+2,1,0);
		for(int i = 0 ; i < M ; i++){
			for(int j = 0 ; j < P ; j++){
				vector<int> tmp;
				int a = r[i];
				int b = p[j];
				for(int k = 0 ; k < 8 ; k++){
					if( a%3-b%3 < 0 ) break;
					tmp.push_back(a%3-b%3);
					a /= 3;
					b /= 3;
				}
				if( tmp.size() != 8 ) continue;
				int enc = 0;
				int wei = 1;
				for(int k = 0 ; k < tmp.size() ; k++){
					enc += tmp[k] * wei;
					wei *= 3;
				}
				Part rem = enc;
				
				int r = dfs({0,0,0,rem});
				if( r < INF ){
					addEdge(g,i+2,2+M+j,1,dfs({0,0,0,rem}));
				}
				
			}
			if( dfs({0,0,0,r[i]}) < INF ) addEdge(g,i+2,emp,1,dfs({0,0,0,r[i]}));
		}
		for(int i = 0 ; i < P ; i++)
			addEdge(g,2+M+i,t,1,0);
		addEdge(g,emp,t,N,0);
		addEdge(g,veryS,s,N,0);
		pair<int,int> res = minimumCostFlow(g,veryS,t);
		if( res.second != N)
			cout << -1 << endl;
		else cout << res.first << endl;
		
		//cout << dfs({0,0,0,{2,0}}) << endl;
	}
}

Measured memory_bytes: 23476