#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int qread() {
register char c = getchar();
register int x = 0, f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + c - 48;
c = getchar();
}
return x * f;
}
inline long long Abs(const long long& x) {return (x > 0 ? x : -x);}
inline long long Max(const long long& x, const long long& y) {return (x > y ? x : y);}
inline long long Min(const long long& x, const long long& y) {return (x < y ? x : y);}
const long long INF = 0x3f3f3f3f3f3f3f3f;
struct Edge {
int to, nxt;
long long cap, cost;
Edge() {
nxt = -1;
}
};
int n, m, hd[1000005], pnt, psum, t[45][105];
Edge e[10000005];
inline void AddEdge(int u, int v, long long cap, long long cost) {
e[pnt].to = v;
e[pnt].cap = cap;
e[pnt].cost = cost;
e[pnt].nxt = hd[u];
hd[u] = pnt;
pnt++;
e[pnt].to = u;
e[pnt].cap = 0;
e[pnt].cost = -cost;
e[pnt].nxt = hd[v];
hd[v] = pnt;
pnt++;
}
inline int Pid(int d, int rk) {return n + (d - 1) * psum + rk;}
inline int D(int pid) {return (pid - n - 1) / psum + 1;}
inline int Rk(int pid) {return (pid - n - 1) % psum + 1;}
namespace MCMF {
long long dis[1000005];
bool inq[1000005], mrk[1000005];
int top[1000005];
inline void SPFA(int s) {
queue <int> que;
que.push(s);
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
while (!que.empty()) {
int u = que.front();
que.pop();
inq[u] = 0;
for (int i = hd[u];~i;i = e[i].nxt) {
if (e[i].cap && dis[e[i].to] > dis[u] + e[i].cost) {
dis[e[i].to] = dis[u] + e[i].cost;
if (!inq[e[i].to]) {
inq[e[i].to] = 1;
que.push(e[i].to);
}
}
}
}
}
inline long long Dfs(int u, int t, long long f) {
if (u == t) return f;
mrk[u] = 1;
long long flw = 0;
for (int i = hd[u];~i;i = e[i].nxt) {
if (e[i].cap && dis[e[i].to] == dis[u] + e[i].cost && !mrk[e[i].to]) {
long long d = Dfs(e[i].to, t, Min(f - flw, e[i].cap));
if (d) {
flw += d;
e[i].cap -= d;
e[i ^ 1].cap += d;
} else dis[e[i].to] = INF;
if (flw == f) break;
}
}
mrk[u] = 0;
return flw;
}
inline long long Flow(int S, int T) {
for (int i = 1;i <= n;i++) top[i] = 1;
long long ans = 0, flw = 0;
while (flw < psum) {
SPFA(S);
long long cur = Dfs(S, T, INF);
flw += cur;
ans += dis[T] * cur;
printf("%lld %lld %lld\n", cur, flw, ans);
for (int i = hd[T];~i;i = e[i].nxt) {
int d = D(e[i].to), rk = Rk(e[i].to);
if (rk == top[d] && top[d] != psum && e[i ^ 1].cap == 0) {
top[d]++;
AddEdge(Pid(d, top[d]), T, 1, 0);
for (int j = 1;j <= n;j++) AddEdge(j, Pid(d, top[d]), 1, 1ll * t[j][d] * top[d]);
}
}
}
return ans;
}
}
inline void Read() {
n = qread(); m = qread();
for (int i = 1;i <= n;i++) {
int p = qread();
psum += p;
AddEdge(0, i, p, 0);
}
for (int i = 1;i <= n;i++) {
for (int j = 1;j <= m;j++) {
t[i][j] = qread();
AddEdge(i, Pid(j, 1), 1, t[i][j]);
if (i == 1) AddEdge(Pid(j, 1), n + m * psum + 1, 1, 0);
}
}
}
int main() {
memset(hd, -1, sizeof(hd));
Read();
printf("%lld", MCMF::Flow(0, n + m * psum + 1));
#ifndef ONLINE_JUDGE
while (1);
#endif
return 0;
}