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

// functions to_inx and from_inx exist to facilitate indexing
int to_inx(const vector<int> &flow, const vector<int> &capacity) {
    const int N = flow.size();
    int ans = 0;
    for (int i = 0; i < N; i++)
        ans = (capacity[i] + 1) * ans + flow[i];
    return ans;
}

void from_inx(int inx, const vector<int> &capacity, vector<int> &flow) {
    for (int i = flow.size() - 1; i >= 0; i--) {
        flow[i] = inx % (capacity[i] + 1);
        inx /= (capacity[i] + 1);
    }
}

// DP[cur_key][cur_chest][f_key][flow] = Cheapest cost to have
//     flow from S to chests described by "flow" (in the sense
//     of to_inx function), flow from cur_key to T == f_key,
//     and only allowing to buy locks for combinations (chest, key)
//     with key < cur_key, or key == cur_key and chest <= cur_chest.
//
// Not a lot of thought was put in the order of the indices, so maybe
//     it's not cache efficient.
int DP[8][8][8][5*5*5*5*5*5];

int main() {
    int n, m;
    scanf("%d %d", &n, &m);

    vector<int> a(n), b(m);
    for (int &x : a) scanf("%d", &x);
    for (int &x : b) scanf("%d", &x);

    vector<vector<int>> c(n, vector<int>(m));
    for (auto &x : c) for (int &y : x) scanf("%d", &y);

    memset(DP, 0x3f, sizeof(DP)); // everything is infinity
    // except the ones with 0 flow
    for (int i = 0; i < m; i++) for (int j = 0; j < n; j++)
        DP[i][j][0][0] = 0; // We can achieve 0 flow for 0 cost

    vector<int> flow_vec(n);
    int max_flow = 1;
    for (int i = 0; i < n; i++) max_flow *= (a[i] + 1);

    for (int key = 0; key < m; key++)
    for (int chest = 0; chest < n; chest++)
    for (int flow_key = 0; flow_key <= b[key]; flow_key++)
    for (int flow = 1; flow < max_flow; flow++) {
        from_inx(flow, a, flow_vec);

        // compute previous state.
        int prev_chest = chest - 1;
        int prev_key = key;
        if (prev_chest == -1) {
            prev_chest = n-1;
            prev_key--;
        }

        // decide on how much flow there is from chest to key
        for (int f = 0; f <= 4; f++) {
            if (flow_key < f || flow_vec[chest] < f) break; // can't send this much flow
            if (prev_key != key && flow_key != f) continue; // if this chest is the only one contributing to the flow of the key, it needs to fulfill all of it

            flow_vec[chest] -= f;
            int prev_flow = to_inx(flow_vec, a);
            flow_vec[chest] += f;

            int prev_cost; // compute the cost that we had BEFORE sending a flow of f from chest to key
            if (prev_key == key) {
                // in this case we know all the indices, since on the previous state we were dealing with the same key.
                prev_cost = DP[prev_key][prev_chest][flow_key - f][prev_flow];
            } else if (prev_key == -1) {
                // This if is synnonym to (chest == 0 && key == 0). In this case there aren't any indices to check,
                //    and we compute the previous cost directly.
                if (prev_flow == 0) prev_cost = 0;
                else prev_cost = 0x3f3f3f3f; // dealing with the first key, there is nothing before
            } else{
                // We just sent the very first flow to this key, so the prev_cost involves a previous key.
                // We don't know how much flow prev_key ended up receiving, so we take the minimum of all options.
                prev_cost = INT_MAX;
                for (int prev_flow_key = 0; prev_flow_key <= b[prev_key]; prev_flow_key++)
                    prev_cost = min(prev_cost, DP[prev_key][prev_chest][prev_flow_key][prev_flow]);
            }

            int new_cost = (f == 0) ? 0 : c[chest][key]; // we only pay for the edges we send flow through

            DP[key][chest][flow_key][flow] = min(DP[key][chest][flow_key][flow], prev_cost + new_cost);
        }
    }

    // the answer is the smallest entry of DP with flow == a, which means that all those edges are saturated
    int target_flow = to_inx(a, a);

    int answer = INT_MAX;
    for (int flow_key = 0; flow_key <= b.back(); flow_key++)
        answer = min(answer, DP[m-1][n-1][flow_key][target_flow]);
    if (answer >= 0x3f3f3f3f) answer = -1;
    printf("%d\n", answer);

    return 0;
}
