#include using namespace std; const int MaxN = (int)1e5 + 10; const int MOD = (int)1e9 + 7; const long long INF = 1e14; struct DinicFlow { struct Edge { int from, to; long long cap, flow; Edge(int _from, int _to, long long _cap, long long _flow) : from(_from), to(_to), cap(_cap), flow(_flow) { } }; vector < Edge > edges; vector < vector < int > > g; vector < int > ptr; vector < long long > dist; int n; void init(int _n) { n = _n; edges.clear(); g.clear(); ptr.clear(); dist.clear(); g.resize(n); dist.resize(n); ptr.resize(n); } void addEdge(int u, int v, long long c) { g[u].push_back(edges.size()); edges.push_back(Edge(u, v, c, 0LL)); g[v].push_back(edges.size()); edges.push_back(Edge(v, u, c, c)); } bool bfs(int s, int t) { for (int i = 0; i < n; ++i) { ptr[i] = 0; dist[i] = INF; } queue < int > q; q.push(s); dist[s] = 0; while (!q.empty()) { int v = q.front(); q.pop(); for (auto id : g[v]) { Edge &cur = edges[id]; if (cur.flow < cur.cap && dist[cur.to] == INF) { dist[cur.to] = dist[cur.from] + 1; q.push(cur.to); } } } return dist[t] != INF; } long long dfs(int v, int t, long long flow) { if (v == t) { return flow; } for (int &i = ptr[v]; i < (int)g[v].size(); ++i) { Edge &cur = edges[g[v][i]]; if (cur.flow < cur.cap && dist[cur.to] == dist[cur.from] + 1) { long long pushed = dfs(cur.to, t, min(flow, cur.cap - cur.flow)); if (pushed > 0) { edges[g[v][i]].flow += pushed; edges[g[v][i] ^ 1].flow -= pushed; return pushed; } } } return 0; } long long getFlow(int s, int t) { long long res = 0; while (bfs(s, t)) { while (true) { long long x = dfs(s, t, INF); if (x == 0) { break; } res += x; } } return res; } }; int cw[1 << 9], cb[1 << 9]; long long aw[1 << 9], ab[1 << 9]; char s[1 << 9][1 << 9]; int n, m; int eval(int i, int j, int k) { return (i - 1) * m + (j - 1) + k * n * m; } void solve() { scanf("%d%d", &n, &m); assert (1 <= n * m && n * m <= 500); for (int i = 1; i <= n; ++i) { scanf("%s", s[i] + 1); assert (strlen(s[i] + 1) == m); for (int j = 1; j <= m; ++j) { assert (s[i][j] == '0' || s[i][j] == '1' || s[i][j] == '?'); } } for (int i = 1; i <= min(n, m); ++i) { scanf("%d", &cw[i]); assert (0 <= cw[i] && cw[i] <= 1e8); aw[i] = cw[i] + aw[i - 1]; } for (int i = 1; i <= min(n, m); ++i) { scanf("%d", &cb[i]); assert (0 <= cb[i] && cb[i] <= 1e8); ab[i] = cb[i] + ab[i - 1]; } DinicFlow df; df.init((2 * n + 1) * n * m + 2); int S = (2 * n + 1) * n * m, T = S + 1; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { df.addEdge(S, eval(i, j, 0), 2 * INF); df.addEdge(eval(i, j, 2 * n), T, 2 * INF); } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { int f = min(n - i, m - j) + 1; for (int k = 1; k <= n; ++k) { if (s[i][j] != '1' && n - k + 1 <= f) { df.addEdge(eval(i, j, k - 1), eval(i, j, k), INF - aw[n - k + 1]); } else { df.addEdge(eval(i, j, k - 1), eval(i, j, k), 2 * INF); } } for (int k = 1; k <= n; ++k) { if (s[i][j] != '0' && k - 1 < f) { df.addEdge(eval(i, j, n + k - 1), eval(i, j, n + k), INF - ab[k]); } else { df.addEdge(eval(i, j, n + k - 1), eval(i, j, n + k), 2 * INF); } } for (int k = 1; k <= i; ++k) { for (int l = 1; l <= j; ++l) { if (k != i || l != j) { int dist = min(max(i - k, j - l), n); df.addEdge(eval(i, j, n), eval(k, l, n - dist), 2 * INF); df.addEdge(eval(k, l, n + dist), eval(i, j, n), 2 * INF); } } } } } cout << INF * n * m - df.getFlow(S, T) << "\n"; } int main() { // freopen("input.txt", "r", stdin); // ios::sync_with_stdio(false); cin.tie(NULL); int t; scanf("%d", &t); while (t --> 0) { solve(); } return 0; }