#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
//typedef complex<D> P;
#define F first
#define S second
const ll MOD=1000000007;
//const ll MOD=998244353;

template<typename T,typename U>istream & operator >> (istream &i,pair<T,U> &A){i>>A.F>>A.S; return i;}
template<typename T>istream & operator >> (istream &i,vector<T> &A){for(auto &I:A){i>>I;} return i;}
template<typename T,typename U>ostream & operator << (ostream &o,const pair<T,U> &A){o<<A.F<<" "<<A.S; return o;}
template<typename T>ostream & operator << (ostream &o,const vector<T> &A){int i=A.size(); for(auto &I:A){o<<I<<(--i?" ":"");} return o;}
template<typename T,typename U>T & chmax(T &a,const U &b){if(a<b){a=b;} return a;}
template<typename T,typename U>T & chmin(T &a,const U &b){if(b<a){a=b;} return a;}

//BEGIN CUT HERE
template <typename T>
struct SegmentTree{
  using F = function<T(T,T)>;
  int n;
  F f;
  T ti;
  vector<T> dat;

  SegmentTree(F f,T ti):f(f),ti(ti){}

  void init(int n_){
    n=1;
    while(n<n_) n<<=1;
    dat.assign(n<<1,ti);
  }

  void build(const vector<T> &v){
    int n_=v.size();
    init(n_);
    for(int i=0;i<n_;i++) dat[n+i]=v[i];
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
  }

  void set_val(int k,T x){
    dat[k+=n]=x;
    while(k>>=1)
      dat[k]=f(dat[(k<<1)|0],dat[(k<<1)|1]);
  }

  T query(int a,int b){
    if(a>=b) return ti;
    T vl=ti,vr=ti;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,dat[l++]);
      if(r&1) vr=f(dat[--r],vr);
    }
    return f(vl,vr);
  }

  template<typename C>
  int find(int st,C &check,T &acc,int k,int l,int r){
    if(l+1==r){
      acc=f(acc,dat[k]);
      return check(acc)?k-n:-1;
    }
    int m=(l+r)>>1;
    if(m<=st) return find(st,check,acc,(k<<1)|1,m,r);
    if(st<=l and !check(f(acc,dat[k]))){
      acc=f(acc,dat[k]);
      return -1;
    }
    int vl=find(st,check,acc,(k<<1)|0,l,m);
    if(~vl) return vl;
    return find(st,check,acc,(k<<1)|1,m,r);
  }

  template<typename C>
  int find(int st,C &check){
    T acc=ti;
    return find(st,check,acc,1,0,n);
  }
};
//END CUT HERE

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  ll H,W,M;
  cin>>H>>W>>M;
  vector<vector<ll>> ROW(H),COL(W);
  for(auto &I:ROW){I.push_back(W);}
  for(auto &I:COL){I.push_back(H);}
  for(int i=0;i<M;i++){
    int X,Y;
    cin>>X>>Y;
    X--; Y--;
    ROW[X].push_back(Y);
    COL[Y].push_back(X);
  }
  for(auto &I:ROW){sort(I.begin(),I.end());}
  for(auto &I:COL){sort(I.begin(),I.end());}
  ll ans=0;

  auto f=[](ll a,ll b){return a+b;};
  SegmentTree<ll> Tr(f,0);
  Tr.build(vector<ll>(3e5,0));

  priority_queue<pll> PQ;

  for(int i=0;i<COL[0][0];i++){ans+=ROW[i][0]; PQ.push({ROW[i][0],i});}
  for(int i=0;i<ROW[0][0];i++){ans+=COL[i][0];}
  for(int i=ROW[0][0]-1;i>=0;i--){
    while(!PQ.empty() && PQ.top().F>i){Tr.set_val(PQ.top().S,1); PQ.pop();}
    ans-=Tr.query(0,COL[i][0]);
  }
  cout<<ans<<endl;
  
  return 0;
}

#include<bits/stdc++.h> 
using namespace std;
namespace Ruri{
    #define ms(a,b) memset(a,b,sizeof(a))
    #define repi(i,a,b) for(int i=a,bbb=b;i<=bbb;++i)//attention reg int or reg ll ?
    #define repd(i,a,b) for(int i=a,bbb=b;i>=bbb;--i)
    #define reps(s) for(int i=head[s],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
    #define ce(i,r) i==r?'\n':' '
    #define pb push_back 
    #define all(x) x.begin(),x.end()
    #define gmn(a,b) a=min(a,b)
    #define gmx(a,b) a=max(a,b)
    #define fi first
    #define se second                         
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    const int infi=1e9;//infi较大，注意涉及inf相加时爆int
    const ll infl=4e18;
    inline ll ceil_div(ll a,ll b){ return (a+b-1)/b; }
    inline ll pos_mod(ll a,ll b){ return (a%b+b)%b; }
    //std::mt19937 rnd(time(0));//std::mt19937_64 rnd(time(0));
}
using namespace Ruri;
namespace Read{
    #define ss(a) scanf("%s",a)
    inline int ri(){ int x; scanf("%d",&x); return x; }
    inline ll rl(){ ll x;  scanf("%lld",&x); return x; }
    inline db rd(){ db x; scanf("%lf",&x); return x; }
}
namespace DeBug{
    #define pr(x) cout<<#x<<": "<<(x)<<endl
    #define pra(x,a,b) cout<<#x<<": "<<endl; \
            repi(i,a,b) cout<<x[i]<<" ";     \
            puts("");   
    #define FR(a) freopen(a,"r",stdin)
    #define FO(a) freopen(a,"w",stdout)
}
using namespace Read;
using namespace DeBug;
const int MAX_N=505;
struct node{ 
	int x,y,z; 
	bool operator <(const node &a)const{ return x<a.x; }
};
typedef pair<ll,node> P;
int r,c;
int a[MAX_N][MAX_N],b[MAX_N][MAX_N];
ll dis[MAX_N][MAX_N][2];
void Dijkstra()
{
	repi(i,1,r)repi(j,1,c) dis[i][j][0]=dis[i][j][1]=infl;
	priority_queue<P,vector<P>,greater<P> > q;
	dis[1][1][1]=0,q.push(P(0,node{1,1,1}));
	while(!q.empty())
	{
		P now=q.top(); q.pop();
		int x=now.se.x,y=now.se.y,z=now.se.z;
		if(dis[x][y][z]<now.fi)	continue;
		if(z==0){
			if(!r) continue;
			if(dis[x-1][y][0]>dis[x][y][z]+1)
				dis[x-1][y][0]=dis[x][y][z]+1,q.push(P(dis[x-1][y][0],node{x-1,y,0}));
			if(dis[x-1][y][1]>dis[x][y][z]+1)
				dis[x-1][y][1]=dis[x][y][z]+1,q.push(P(dis[x-1][y][1],node{x-1,y,1}));
		}
		else{
			if(y<c&&dis[x][y+1][z]>dis[x][y][z]+a[x][y])
				dis[x][y+1][z]=dis[x][y][z]+a[x][y],q.push(P(dis[x][y+1][z],node{x,y+1,z}));

			if(y&&dis[x][y-1][z]>dis[x][y][z]+a[x][y-1])
				dis[x][y-1][z]=dis[x][y][z]+a[x][y-1],q.push(P(dis[x][y-1][z],node{x,y-1,z}));

			if(x<r&&dis[x+1][y][z]>dis[x][y][z]+b[x][y])
				dis[x+1][y][z]=dis[x][y][z]+b[x][y],q.push(P(dis[x+1][y][z],node{x+1,y,z}));

			if(r&&dis[x][y][0]>dis[x][y][z]+1)
				dis[x][y][0]=dis[x][y][z]+1,q.push(P(dis[x][y][0],node{x,y,0}));
		}
		

	}	
}
int main()
{
	r=ri(),c=ri();
	repi(i,1,r)repi(j,1,c-1) a[i][j]=ri();
	repi(i,1,r-1)repi(j,1,c) b[i][j]=ri();
	Dijkstra();
	printf("%lld\n",dis[r][c][1]);
    return 0;
}