1 /**************************************************************
2 Problem: 1001
3 User: shadowland
4 Language: C++
5 Result: Accepted
6 Time:2752 ms
7 Memory:165356 kb
8 ****************************************************************/
9
10 #include "bits/stdc++.h"
11
12 using namespace std ;
13 struct Edge { int to , next , val ; } ;
14 const int maxN = 8000100 ;
15
16 Edge e[ maxN ] ;
17 int head[ maxN ] , Dis[ maxN ] ;
18 bool vis[ maxN ] ;
19
20 int N , M , cnt ;
21
22 inline int INPUT ( ) {
23 int x = 0 , f = 1 ; char ch = getchar ( ) ;
24 while ( ch < ‘0‘ || ch > ‘9‘ ) { if ( ch == ‘-‘)f = -1 ; ch = getchar ( ) ;}
25 while ( ch >= ‘0‘ && ch <= ‘9‘ ) { x = ( x << 1 ) + ( x << 3 ) + ch - ‘0‘ ; ch = getchar ( ) ;}
26 return x * f ;
27 }
28
29 inline int Get ( const int x , const int y , const int z ) {
30 if ( x < 1 || y >=M ) return ( N - 1 ) * ( M - 1 ) * 2 + 2 ;
31 if ( x >= N || y < 1 ) return 1 ;
32 return ( ( x - 1 ) * ( M - 1 ) + y ) *2 + z ;
33 }
34
35 inline void Add_Edge ( const int x , const int y , const int _val ) {
36 e[ ++cnt ].to = y ;
37 e[ cnt ].val = _val ;
38 e[ cnt ].next = head[ x ] ;
39 head[ x ] = cnt ;
40 }
41
42 void SPFA ( const int S ) {
43 memset ( vis , false , sizeof ( vis ) ) ;
44 memset ( Dis , 0x3f , sizeof ( Dis ) ) ;
45 queue < int > Q ;
46 Dis[ S ] = 0 ;
47 vis[ S ] = true ;
48 Q.push ( S ) ;
49 while ( !Q.empty ( ) ) {
50 int t = Q.front( ) ; Q.pop ( ) ; vis[ t ] = false ;
51 for ( int i=head[ t ] ; i ; i = e[ i ].next ) {
52 int temp = e[ i ].to ;
53 if ( Dis[ temp ] > Dis[ t ] + e[ i ].val ) {
54 Dis[ temp ] = Dis[ t ] + e[ i ].val ;
55 if ( !vis[ temp ] ) {
56 Q.push ( temp ) ;
57 vis[ temp ] = true ;
58 }
59 }
60 }
61 }
62 }
63
64 void DEBUG_ ( int N , int M ) {
65 printf ( "\n" ) ;
66 for ( int i=1 ; i<=(( N - 1 ) * ( M - 1 ) * 2 + 2) ; ++i ) {
67 printf ( "%d " , Dis[ i ] ) ;
68 }
69 }
70 int main ( ) {
71 int _val ;
72 scanf ( "%d %d" , &N , &M ) ;
73 for ( int i=1 ; i<=N ; ++i ) {
74 for ( int j=1 ; j<M ; ++j ) {
75 _val = INPUT ( ) ;
76 Add_Edge ( Get ( i , j , 1 ) , Get ( i - 1 , j , 0 ) , _val ) ;
77 Add_Edge ( Get ( i - 1 , j , 0 ) , Get ( i , j , 1 ) , _val ) ;
78 }
79 }
80 for ( int i=1 ; i<N ; ++i ) {
81 for ( int j=1 ; j<=M ; ++j ) {
82 _val = INPUT ( ) ;
83 Add_Edge ( Get ( i , j - 1 , 1 ) , Get ( i , j , 0 ) , _val ) ;
84 Add_Edge ( Get ( i , j , 0 ) , Get ( i , j - 1 , 1 ) , _val ) ;
85 }
86 }
87 for ( int i=1 ; i<N ; ++i ) {
88 for ( int j=1 ; j<M ; ++j ) {
89 _val = INPUT ( ) ;
90 Add_Edge ( Get ( i , j , 0 ) , Get ( i , j , 1 ) , _val ) ;
91 Add_Edge ( Get ( i , j , 1 ) , Get ( i , j , 0 ) , _val ) ;
92 }
93 }
94 SPFA ( 1 ) ;
95 printf ( "%d\n" , Dis[ ( N - 1 ) * ( M - 1 ) * 2 + 2 ] ) ;
96 //DEBUG_( N , M ) ;
97
98 return 0 ;
99 }