#include<bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;

//Input
int D; // D:授業の回数
int K; // K:部品の種類の数
int L; // L:1日に購入することができる部品の数
int Cost[8][8]; // Cost[d][k]:d日目の部品kの価格
int M; // M:課題の種類の数
int N; // N:生徒の人数
int P; // P:袋の数
int R[200][8]; // R[m][k]:課題mに必要な部品kの個数
int T[200][8]; // T[p][k]:袋pに入っている部品kの個数

int dp[9][3][3][3][3][3][3][3][3]; //dp[i][many]: 部品集合manyをi日目にまでに買うための最小費用

typedef pair< int, int > Pi;
#define MAX_V 50200
int n;
class Primal_Dual{
private:
  struct edge{
    int to, cap, cost, rev;
  };
  int V;
  vector< edge > info[MAX_V];
  int h[MAX_V], dist[MAX_V], prevv[MAX_V], preve[MAX_V];
public:
  void add_edge(int from,int to,int cap,int cost){ //from,to,容量,コスト
    info[from].push_back((edge){to,cap,cost,info[to].size()});
    info[to].push_back((edge){from,0,-cost,info[from].size()-1});
  }
  Primal_Dual(){};
  Primal_Dual(int size):V(size){};
  int min_cost_flow(int s,int t,int f){ //sからtへの最小費用流
    int ret = 0;
    fill_n( h, V, 0);
    while(f > 0){
      priority_queue< Pi, vector< Pi >, greater< Pi > > que;
      fill_n( dist, V, INF);
      que.push(Pi(0,s));
      dist[s] = 0;
      while(!que.empty()){
        Pi p = que.top(); que.pop();
        if(dist[p.second] < p.first) continue;
        for(int i = 0; i < info[p.second].size(); i++){
          edge& e = info[p.second][i];
          if(e.cap > 0 && dist[e.to] > dist[p.second] + e.cost + h[p.second] - h[e.to]){
            dist[e.to] = dist[p.second] + e.cost + h[p.second] - h[e.to];
            prevv[e.to] = p.second, preve[e.to] = i;
            que.push(Pi(dist[e.to],e.to));
          }
        }
      }
      if(dist[t] == INF) return -1;
      for(int v = 0; v < V; v++) h[v] += dist[v];
      int d = f;
      for(int v = t; v != s; v = prevv[v]){
        d = min( d, info[prevv[v]][preve[v]].cap);
      }
      f -= d;
      ret += d * h[t];
      for(int v = t; v != s; v = prevv[v]){
        edge& e = info[prevv[v]][preve[v]];
        e.cap -= d;
        info[v][e.rev].cap += d;
      }
    }
    return ret;
  }
};
int main()
{

  while(cin >> D >> K >> L, D){
    fill_n( *Cost, 8 * 8, 0);
    fill_n( *R, 200 * 8, 0);
    fill_n( *T, 200 * 8, 0);
    fill_n( ********dp, 9 * 3 * 3 * 3 * 3 * 3 * 3 * 3 * 3, INF);

    for(int i = 0; i < D; i++){
      for(int j = 0; j < K; j++){
        cin >> Cost[i][j];
      }
    }
    cin >> M >> N >> P;
    for(int i = 0; i < M; i++){
      for(int j = 0; j < K; j++){
        cin >> R[i][j];
      }
    }
    for(int i = 0; i < P; i++){
      for(int j = 0; j < K; j++){
        cin >> T[i][j];
      }
    }


    dp[0][0][0][0][0][0][0][0][0] = 0;
#define rep(i,n) for(int i = 0; i < n; i++)
#define reps(i,a,n) for(int i = a; i < n; i++)
    for(int i = 0; i < D; i++){
      rep(a,3) rep(b,3) rep(c,3) rep(d,3) rep(e,3) rep(f,3) rep(g,3) rep( h,3){ //今の状態
        if(dp[i][a][b][c][d][e][f][g][h] == INF) continue;
        reps(A,a,3) reps(B,b,3) reps(C,c,3) reps(D,d,3) reps(E,e,3) reps(F,f,3) reps(G,g,3) reps(H,h,3){
          if(A + B + C + D + E + F + G + H - a - b - c - d - e - f - g - h > L) continue;
          dp[i + 1][A][B][C][D][E][F][G][H] =
            min( dp[i + 1][A][B][C][D][E][F][G][H], dp[i][a][b][c][d][e][f][g][h] + Cost[i][0] * (A - a) + Cost[i][1] * (B - b) + Cost[i][2] * (C - c) + Cost[i][3] * (D - d) + Cost[i][4] * (E - e) + Cost[i][5] * (F - f) + Cost[i][6] * (G - g) + Cost[i][7] * (H - h));
        }
      }
    }
    Primal_Dual pd(P + M + 3);

    int source = P + M + 1;
    int end = P + M + 2;
    pd.add_edge( source, 0, INF, 0);
    for(int i = 1; i <= P; i++){
      pd.add_edge( source, i, 1, 0);
    }
    for(int i = 0; i < M; i++){
      if(dp[D][R[i][0]][R[i][1]][R[i][2]][R[i][3]][R[i][4]][R[i][5]][R[i][6]][R[i][7]] == INF) continue;
      pd.add_edge( 0, P + 1 + i, 1, dp[D][R[i][0]][R[i][1]][R[i][2]][R[i][3]][R[i][4]][R[i][5]][R[i][6]][R[i][7]]);
    }
    for(int i = 1; i <= P; i++){ //袋i
      for(int j = 0; j < M; j++){ //課題j
        bool flag = true;
        for(int k = 0; k < 8; k++){
          if(R[j][k] - T[i - 1][k] < 0) flag = false;
        }
        if(!flag) continue;
        if(dp[D][R[j][0] - T[i - 1][0]][R[j][1] - T[i - 1][1]][R[j][2] - T[i - 1][2]][R[j][3] - T[i - 1][3]][R[j][4] - T[i - 1][4]][R[j][5] - T[i - 1][5]][R[j][6] - T[i - 1][6]][R[j][7] - T[i - 1][7]] == INF) continue;
        pd.add_edge( i, P + 1 + j, 1, dp[D][R[j][0] - T[i - 1][0]][R[j][1] - T[i - 1][1]][R[j][2] - T[i - 1][2]][R[j][3] - T[i - 1][3]][R[j][4] - T[i - 1][4]][R[j][5] - T[i - 1][5]][R[j][6] - T[i - 1][6]][R[j][7] - T[i - 1][7]]);
      }
    }
    for(int i = 0; i < M; i++){
      pd.add_edge( P + 1 + i, end, 1, 0);
    }
    cout << pd.min_cost_flow( source, end, N) << endl;
  }
}

Measured memory_bytes: 4320