1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 #include <queue>
5 const int N = 1000 + 7, M = 2000000 + 7, inf = 1 << 30;
6 using namespace std;
7 int n,m,s,t,cnt,head[M],dis[M];
8 bool used[M];
9 struct edges
10 {
11 int nxt,to,wi;
12 } E[M * 3];
13
14 int idid(int a,int b)
15 {
16 return (a - 1) * (m - 1) * 2 + b * 2;
17 }
18
19 void add(int u,int v,int wi)
20 {
21 E[++cnt] = (edges){head[u],v,wi};head[u] = cnt;
22 E[++cnt] = (edges) {head[v],u,wi}; head[v] = cnt;
23 }
24
25 void Init()
26 {
27 scanf("%d%d",&n,&m);
28 if(n == 1 || m == 1)
29 {
30 if(n == 1) swap(n,m);
31 int ans = inf, c;
32 for(int i = 1; i < n; ++i)
33 {
34 scanf("%d",&c);
35 ans = min(ans,c);
36 }
37 printf("%d\n",ans); return;
38 }
39 int c;s = 0, t = ((n-1) * (m-1) << 1) + 1;
40 for(int i = 1; i <= n; ++i)
41 for(int j = 1; j < m; ++j)
42 {
43 scanf("%d",&c);
44 if(i == 1) add(s,j<<1,c);
45 else if(i == n) add(idid(i-1,j)-1,t,c);
46 else add(idid(i-1,j)-1,idid(i,j),c);
47 }
48
49 for(int i = 1; i < n; ++i)
50 for(int j = 1; j <= m; ++j)
51 {
52 scanf("%d",&c);
53 if(j == 1) add(idid(i,j)-1,t,c);
54 else if(j == m) add(s,idid(i,j-1),c);
55 else add(idid(i,j-1),idid(i,j)-1,c);
56 }
57 for(int i = 1;i < n; ++i)
58 for(int j = 1 ; j < m; ++j)
59 {
60 scanf("%d",&c);
61 add(idid(i,j)-1,idid(i,j),c);
62 }
63 }
64
65 void dij()
66 {
67 queue<int> Q;
68 memset(dis,127/2,sizeof(dis));
69 memset(used,false,sizeof(used)); used[s] = true;
70 Q.push(s); dis[s] = 0;
71 while(!Q.empty())
72 {
73 int u = Q.front(); Q.pop(); used[u] = false;
74 for(int i = head[u]; i; i = E[i].nxt)
75 {
76 int v = E[i].to;
77 if(dis[v] <= dis[u] + E[i].wi) continue;
78 dis[v] = dis[u] + E[i].wi;
79 if(used[v]) continue;
80 Q.push(v); used[v] = true;
81 }
82 }
83 }
84
85 void Solve()
86 {
87 dij();
88 printf("%d\n",dis[t]);
89 }
90
91 int main()
92 {
93 // freopen("1.in","r",stdin);
94 Init();
95 if(n == 1 || m == 1) return 0;
96 Solve();
97 return 0;
98 }
99