import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag

object Main extends App {

  import scala.io.StdIn._
  implicit object G extends Group[Int] {
    override def plus(a: Int, b: Int): Int = a + b

    override def minus(a: Int, b: Int): Int = a - b

    override def times(a: Int, b: Int): Int = a * b

    override def maxSentinel: Int = Int.MaxValue

    override def zero: Int = 0
  }
  solve
  def solve: Unit = {
    val Array(d, k, l) = readLine.trim.split(' ').map(_.toInt)
    if (d == 0) return
    val prices = Array.tabulate(d){_ ⇒ readLine.trim.split(' ').map(_.toInt)}
    val Array(m, n, p) = readLine.trim.split(' ').map(_.toInt)
    val crafts = Array.tabulate(m){_ ⇒ readLine.trim.split(' ').map(_.toInt)}
    val bags = Array.tabulate(p){_ ⇒ readLine.trim.split(' ').map(_.toInt)} :+ Array.tabulate(k){_ ⇒ 0}
    val forDays = Array.tabulate(d){i ⇒ (0, i + 1, l, 0)}
    val costs = crafts.map{
      case craft ⇒
        bags.indices.withFilter{i ⇒
          bags(i).indices.forall(j ⇒ craft(j) >= bags(i)(j))
        }.flatMap{i ⇒
          val needs = bags(i).indices.map(j ⇒ craft(j) - bags(i)(j)).toArray
          val edges = ArrayBuffer[(Int, Int, Int, Int)](forDays:_*)
          for (item ← needs.indices if needs(item) > 0){
            edges.append((item + d + 1, k + d + 1, needs(item), 0))
            for (day ← prices.indices){
              edges.append((day + 1, item + d + 1, needs(item), prices(day)(item)))
            }
          }
          //from, to, capacity, cost, source=> 0 drain => k + d + 1
          // day(1 to d), item(d + 1 to d + k)
          val (flow, cost) = minCostFlowMatching(0, k + d + 1, k + d + 2, edges.toArray)
          if (flow == needs.sum) Some((i, cost))
          else None
        }.toArray
    }
    //source = 0 drain = m + p + 2
    //craft(1 to m), bag(m + 1 to m + p + 1)
    val edge = ArrayBuffer[(Int, Int, Int, Int)]()
    for (craft ← costs.indices) {
      edge.append((0, craft + 1, 1, 0))
      for (bag ← costs(craft).indices) {
        val (i, c) = costs(craft)(bag)
        edge.append((craft + 1, i + m + 1, 1, c))
      }
    }
    for (i ← 0 until p) edge.append((m + i + 1, m + p + 2, 1, 0))
    edge.append((m + p + 1, m + p + 2, n, 0))
    val (flow, cost) = minCostFlowMatching(0, m + p + 2, m + p + 3, edge.toArray, n)
    if (flow == n) println(cost)
    else println(-1)
    solve
  }
  implicit class Extend[T](value: T){
    def let[R](func: T ⇒ R): R = func(value)
    def also(func: T ⇒ Unit): T = {func(value); value}
  }

  trait Group[T]{
    def plus(a: T, b: T): T
    def minus(a: T, b: T): T
    def times(a: T, b: Int): T
    def maxSentinel: T
    def zero: T
  }

  //edge => (from, to, capacity, cost)
  def minCostFlowMatching[N : ClassTag](source: Int, drain: Int, size: Int, edge: Array[(Int, Int, Int, N)], flowLimit: Int = Int.MaxValue)(implicit m: Group[N], o: Ordering[N]): (Int, N) = {
    val edges = makeGraph(size, edge)
    val potential = Array.tabulate(size){_ ⇒ m.maxSentinel}
    for (e ← edges) for (Edge(to, cap, _, c) ← e if cap > 0 && o.compare(potential(to), c) > 0) potential(to) = c
    potential(source) = m.zero
    potential(drain) = m.zero
    val prevEdge = Array.tabulate(size){_ ⇒ (Edge(-1, -1, -1, m.zero), Int.MaxValue)}
    val minCost = Array.tabulate(size){_ ⇒ m.maxSentinel}
    val queue = mutable.PriorityQueue()(Ordering.by[(Int, N), N](_._2).reverse)
    var canMatch = true
    var result = m.zero
    var totalFlow = 0
    while(canMatch) {
      canMatch = false
      queue.enqueue((source, m.zero))
      minCost.indices.foreach(i ⇒ minCost(i) = m.maxSentinel)
      minCost(source) = m.zero
      while(queue.nonEmpty){
        val (prev, cost) = queue.dequeue()
        if (prev != drain && o.compare(minCost(prev), cost) == 0){
          for (e@Edge(to, cap, pair, c) ← edges(prev) if cap > 0){
            //minCost(to) > potential(prev) + c - potential(to) + cost
            if (o.equiv(minCost(to), m.maxSentinel) || o.compare(m.minus(m.minus(minCost(to), potential(prev)), cost), m.minus(c, potential(to))) > 0) {
              minCost(to) = m.plus(m.minus(potential(prev), potential(to)), m.plus(c, cost))
              prevEdge(to) = (edges(to)(pair), math.min(prevEdge(prev)._2, cap))
              queue.enqueue((to, minCost(to)))
            }
          }
        }
      }
      if (!o.equiv(minCost(drain), m.maxSentinel)) {
        canMatch = true
        var last = drain
        val bottleNeck = prevEdge(drain)._2
        //var current = minCost(drain)
        while (last != source) {
          val (r, _) = prevEdge(last)
          val e = edges(r.to)(r.pair)
          edges(last)(e.pair) = r.copy(capacity = r.capacity + bottleNeck)
          edges(r.to)(r.pair) = e.copy(capacity = e.capacity - bottleNeck)
          last = r.to
        }
        if (totalFlow + bottleNeck <= flowLimit) {
          totalFlow += bottleNeck
          result = m.plus(result, m.times(minCost(drain), bottleNeck))
        } else {
          result = m.plus(result, m.times(minCost(drain), flowLimit - totalFlow))
          totalFlow = flowLimit
          canMatch = false
        }
        for (x ← 0 until size if x != source && x != drain){
          potential(x) = m.plus(potential(x), minCost(x))
        }
      }
    }
    (totalFlow, result)
  }
  private case class Edge[N](to: Int, capacity: Int, pair: Int, cost: N)
  private def makeGraph[N](size: Int, edge: Array[(Int, Int, Int, N)])(implicit m: Group[N]): Array[Array[Edge[N]]] = {
    val nodes = Array.tabulate(size){_ ⇒ ArrayBuffer[Edge[N]]()}
    for ((from, to, capacity, cost) ← edge){
      nodes(from).append(Edge(to, capacity, nodes(to).length, cost))
      nodes(to).append(Edge(from, 0, nodes(from).length - 1, m.minus(m.zero, cost)))
    }
    nodes.map{_.toArray}
  }
}


Measured memory_bytes: 585116