#include <cstdio> #include <cstring> #include <climits> #include <queue> #include <algorithm> #include <functional> const int MAX_N = 1000; const int MAX_M = 1000; const int MAX_NODE = MAX_N * MAX_M * 2 + 2; struct Node; struct Edge; struct Node { Edge *e; int dist; bool vis; } N[MAX_NODE]; struct Edge { Node *fr, *to; Edge *ne; int w; Edge(Node *fr, Node *to, int w) : fr(fr), to(to), ne(fr->e), w(w) {} }; inline void addEdge(int fr, int to, int w) { N[fr].e = new Edge(&N[fr], &N[to], w); N[to].e = new Edge(&N[to], &N[fr], w); } inline int djk(int begin, int end, int n) { Node *s = &N[begin], *t = &N[end]; std::priority_queue< std::pair<int, Node *>, std::vector< std::pair<int, Node *> >, std::greater< std::pair<int, Node *> > > q; for (int i = 0; i < n; i++) N[i].dist = INT_MAX, N[i].vis = false; s->dist = 0; q.push(std::make_pair(s->dist, s)); while (!q.empty()) { Node *v = q.top().second; q.pop(); if (v->vis) continue; v->vis = true; for (Edge *e = v->e; e; e = e->ne) { if (e->to->dist > v->dist + e->w) { e->to->dist = v->dist + e->w; q.push(std::make_pair(e->to->dist, e->to)); } } } return t->dist; } int n, m; inline int id(int i, int j) { return (i - 1) * 2 * (m - 1) + j; } inline int solve() { if (n == 1 && m == 1) return 0; else if (n == 1) { int ans = INT_MAX; for (int i = 0; i < m - 1; i++) { int w; scanf("%d", &w); ans = std::min(ans, w); } return ans; } else if (m == 1) { int ans = INT_MAX; for (int i = 0; i < n - 1; i++) { int w; scanf("%d", &w); ans = std::min(ans, w); } return ans; } int s = 2 * (m - 1) * (n - 1), t = s + 1; for (int i = 1; i <= n; i++) { for (int j = 0; j < m - 1; j++) { int w; scanf("%d", &w); if (i == 1) { addEdge(id(i, (j * 2) ^ 1), t, w); } else if (i == n) { addEdge(s, id(i - 1, j * 2), w); } else { addEdge(id(i, (j * 2) ^ 1), id(i - 1, j * 2), w); } } } for (int i = 1; i < n; i++) { for (int j = 0; j < m; j++) { int w; scanf("%d", &w); if (j == 0) { addEdge(s, id(i, j * 2), w); } else if (j == m - 1) { addEdge(id(i, ((j - 1) * 2) ^ 1), t, w); } else { addEdge(id(i, ((j - 1) * 2) ^ 1), id(i, (j * 2)), w); } } } for (int i = 1; i < n; i++) { for (int j = 0; j < m - 1; j++) { int w; scanf("%d", &w); addEdge(id(i, j * 2), id(i, (j * 2) ^ 1), w); } } return djk(s, t, t + 1); } int main() { scanf("%d %d", &n, &m); printf("%d\n", solve()); return 0; }
|