// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

const int INF=1001001001;

const int MAX_V=1000;

const int S=MAX_V-2,T=MAX_V-1;

struct edge{

    int to,cap,cost,rev;

    edge(int to,int cap,int cost,int rev)

        :to(to),cap(cap),cost(cost),rev(rev){}

};

vector<edge>G[MAX_V];

int dist[MAX_V];

int prevv[MAX_V],preve[MAX_V];



void add_edge(int from,int to,int cap,int cost){

    G[from].push_back(edge(to,cap,cost,G[to].size()));

    G[to].push_back(edge(from,0,-cost,G[from].size()-1));

}



int min_cost_flow(int s,int t,int f){

    int res=0;

    while(f>0){

        fill_n(dist,MAX_V,INF);

        dist[s]=0;

        bool update=true;

        while(update){

            update=false;

            for(int v=0;v<MAX_V;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.to]>dist[v]+e.cost){

                        dist[e.to]=dist[v]+e.cost;

                        prevv[e.to]=v;

                        preve[e.to]=i;

                        update=true;

                    }

                }

            }

        }



        if(dist[t]==INF)return -1;



        int d=f;

        for(int v=t;v!=s;v=prevv[v]){

            edge &e=G[prevv[v]][preve[v]];

            d=min(d,e.cap);

        }



        f-=d;

        res+=dist[t]*d;

        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;

}



int D,K,L;

int M,N,P;

int c[8][8],r[200],t[200];



int cost[1<<16];

int dp[9][1<<16];



void DPing(){

    fill_n(*dp,9*(1<<16),INF);

    dp[0][0]=0;

    for(int i=0;i<D;i++){

        for(int j=0;j<L;j++){

            for(int k=0;k<(1<<(2*K));k++){

                for(int l=0;l<K;l++){

                    if((k>>(2*l)&3)>=2)continue;

                    dp[j+1][k+(1<<(2*l))]=min(dp[j+1][k+(1<<(2*l))],dp[j][k]+c[i][l]);

                }

            }

        }

        for(int j=0;j<(1<<(2*K));j++){

            for(int k=1;k<=L;k++){

                dp[0][j]=min(dp[0][j],dp[k][j]);

                dp[k][j]=INF;

            }

        }

    }



    for(int i=0;i<(1<<(2*K));i++){

        cost[i]=dp[0][i];

    }

}



bool in(int a,int b){

    for(int i=0;i<K;i++){

        int va=a>>(i*2)&3;

        int vb=b>>(i*2)&3;

        if(va>vb)return false;

    }

    return true;

}



void solve(){

    DPing();

    fill_n(G,MAX_V,vector<edge>());



    for(int i=0;i<M;i++)add_edge(S,i,1,0);

    for(int i=0;i<P;i++)add_edge(M+i,T,1,0);

    for(int i=0;i<M;i++){

        if(cost[r[i]]!=INF)add_edge(i,T,1,cost[r[i]]);

        for(int j=0;j<P;j++){

            if(in(t[j],r[i])&&cost[r[i]-t[j]]!=INF){

                add_edge(i,M+j,1,cost[r[i]-t[j]]);

            }

        }

    }



    cout<<min_cost_flow(S,T,N)<<endl;





}



int get(){

    int ret=0;

    for(int i=0;i<K;i++){

        int v;cin>>v;

        ret+=v<<(i*2);

    }

    return ret;

}



int main(){

    while(cin>>D>>K>>L,D||K||L){

        for(int i=0;i<D;i++)for(int j=0;j<K;j++)cin>>c[i][j];

        cin>>M>>N>>P;

        for(int i=0;i<M;i++)r[i]=get();

        for(int i=0;i<P;i++)t[i]=get();

        solve();

    }





    return 0;

}

// Optimized solution to the same problem (faster):
#include<cstdio>

#include<vector>

#include<algorithm>

#include<iostream>

#include<cassert>

#include<cstring>

#include<queue>

#include<stack>

#include<map>

#include<set>

#include<string>

#include<climits>

using namespace std;

typedef pair<int,int>pint;

typedef vector<int>vint;

#define pb push_back

#define mp make_pair

#define rep(i,n) for(int i=0;i<(n);i++)

template<class T,class U>void chmin(T &t,U f){if(t>f)t=f;}

template<class T,class U>void chmax(T &t,U f){if(t<f)t=f;}



const int INF=1001001001;



int D,K,L;

int c[8][8];



int M,N,P;

int r[200];

int t[200];

int dp[1<<16];

void dping(){

    fill_n(dp,1<<16,INF);



    dp[0]=0;



    rep(i,D)rep(latte,L){

        for(int j=(1<<(2*K))-1;j>=0;j--){

            rep(k,K){

                if((j>>(2*k)&3)>=2)continue;

                chmin(dp[j+(1<<(2*k))],dp[j]+c[i][k]);

            }

        }

    }

}



struct edge{

    int to,cap,cost,rev;

    edge(int to,int cap,int cost,int rev):to(to),cap(cap),cost(cost),rev(rev){}

};



const int MAX_V=500;

int S=MAX_V-2,T=MAX_V-1;

int V;

vector<edge>G[MAX_V];

int dist[MAX_V];

int prevv[MAX_V],preve[MAX_V];



void add_edge(int from,int to,int cap,int cost){

    G[from].pb(edge(to,cap,cost,G[to].size()));

    G[to].pb(edge(from,0,-cost,G[from].size()-1));

}



int min_cost_flow(int s,int t,int f){

    int res=0;

    while(f>0){

        fill_n(dist,MAX_V,INF);

        dist[s]=0;

        bool update=true;

        while(update){

            update=false;

            rep(v,MAX_V){

                if(dist[v]==INF)continue;

                rep(i,G[v].size()){

                    edge &e=G[v][i];

                    if(e.cap>0&&dist[e.to]>dist[v]+e.cost){

                        dist[e.to]=dist[v]+e.cost;

                        prevv[e.to]=v;

                        preve[e.to]=i;

                        update=true;

                    }

                }

            }

        }



        if(dist[t]==INF)return -1;



        int d=f;

        for(int v=t;v!=s;v=prevv[v]){

            chmin(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;

}



int main(){

    while(cin>>D>>K>>L,D||K||L){

        memset(r,0,sizeof(r));memset(t,0,sizeof(t));

        rep(i,MAX_V)G[i].clear();



        rep(i,D)rep(j,K)cin>>c[i][j];



        cin>>M>>N>>P;



        rep(i,M){

            rep(j,K){

                int a;cin>>a;

                r[i]|=a<<(j*2);

            }

        }



        rep(i,P){

            rep(j,K){

                int a;cin>>a;

                t[i]|=a<<(j*2);

            }

        }



        dping();



        rep(i,M){

            add_edge(S,i,1,0);

            if(r[i]!=INF)add_edge(i,T,1,dp[r[i]]);

        }

        rep(i,P){

            add_edge(M+i,T,1,0);

        }

        rep(i,M){

            rep(j,P){

                bool ok=true;

                rep(k,K)if((r[i]>>(2*k)&3)<(t[j]>>(2*k)&3))ok=false;

                if(ok)add_edge(i,M+j,1,dp[r[i]-t[j]]);



            }

        }

        cout<<min_cost_flow(S,T,N)<<endl;

    }

    return 0;

}

// Fastest known solution for this problem: