#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <iostream>
#include <fstream>
#include <numeric>
#include <cstring>
#include <cassert>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <cmath>
#include <set>
#include <map>
#include <functional>
#include <bitset>
#include <iomanip>
#include <stack>
#include <list>
#include <cstdint>
#include <chrono>
#include <hash_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

using namespace __gnu_pbds;
using namespace std;

#define     lp(i,a,n)       for(ll i=a;i<n;i++)
#define     lp2(i,n,a)      for(ll i=a-1;i>=n;i--)
#define     all(arr,n)      arr,arr+n
#define     allv(v)         (v).begin(),(v).end()
#define     rallv(v)        (v).rbegin(),(v).rend()
#define     m_p             make_pair
#define     ll              long long
#define     pii             pair<ll,ll>
#define     vi              vector<int>
#define     vll             vector<ll>
#define     vii             vector<pii>
#define     sz(x)           (int)x.size()
#define     pb              push_back
#define     endl            '\n'
#define     Endl            '\n'
#define     f               first
#define     s               second
#define     mem(dp,n)       memset(dp,n,sizeof dp)
#define     ordered_set     tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>
template<typename T>void max_self(T &a,T b){a=max(a,b);}
template<typename T>void min_self(T &a,T b){a=min(a,b);}
int dx[] = { 1 , 0 ,-1 , 0 ,-1 ,-1 , 1 , 1 };
int dy[] = { 0 , 1 , 0 ,-1 ,-1 , 1 ,-1 , 1 };
int KnightX[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int KnightY[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
void fast(){
    std::ios_base::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
}
vector<string> vec_splitter(string s) {
    s += ',';
    vector<string> res;
    while(!s.empty()) {
        res.push_back(s.substr(0, s.find(',')));
        s = s.substr(s.find(',') + 1);
    }
    return res;
}
void debug_out(
        vector<string> __attribute__ ((unused)) args,
        __attribute__ ((unused)) int idx,
        __attribute__ ((unused)) int LINE_NUM) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, int LINE_NUM, Head H, Tail... T) {
    if(idx > 0) cerr << ", "; else cerr << "Line(" << LINE_NUM << ") ";
    stringstream ss; ss << H;
    cerr << args[idx] << " = " << ss.str();
    debug_out(args, idx + 1, LINE_NUM, T...);
}
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __LINE__, __VA_ARGS__)
const ll mxN=5e5,oo=0x3f3f3f3f,MOD=998244353;
const long double PI = acos(-1),eps=1e-9;

void solve(){
    int a,b;
    cin>>a>>b;
    int sa=0,sb=0;
    while(a)
        sa+=(a%10),a/=10;
    while(b)
        sb+=(b%10),b/=10;
    cout<<max(sa,sb);
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    fast();
    int t=1;
    //cin>>t;
    while(t--)
        solve();
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp>
// using namespace __gnu_pbds;
//indexed set is using "int" here--------- use ll ...
// typedef tree <int,null_type,less <int>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
typedef long long int ll;
typedef long double ld;
#define FAST                 \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0);
#define rep(g, i, n) for (ll g = i; g < n; g++)
#define rev(g, n, i) for (ll g = n - 1; g >= i; g--)
#define all(v) v.begin(), v.end()
#define pb push_back
#define mxe(v) *max_element(v.begin(), v.end())
#define mne(v) *min_element(v.begin(), v.end())
#define ve vector
#define rem 1000000007
#define PI 3.141592653589793238462643383279502
ll power(ll x, ll y, ll p)
{
    ll res = 1; // Initialize result
    x = x % p;  // Update x if it is more than or
    while (y > 0)
    {
        if (y & 1)
            res = (res * x) % p;
        y = y >> 1; // y = y/2
        x = (x * x) % p;
    }
    return res;
}
ll modInverse(ll n, ll p)
{
    return power(n, p - 2, p);
}
void solve_dp(ve<ve<ll>> &dp, ll r, ll c, ve<ve<ll>> &A, ve<ve<ll>> &B)
{
    dp[1][1] = 0;
    rep(i, 1, r + 1)
    {
        rep(j, 1, c + 1)
        {
            if (i == 1)
            {
                dp[i][j] = min(dp[i][j], dp[i][j - 1] + A[i][j - 1]);
                continue;
            }
            if (j == 1)
            {
                dp[i][j] = min(dp[i][j], dp[i - 1][j] + B[i - 1][j]);
                continue;
            }
            dp[i][j] = min({dp[i][j], dp[i][j - 1] + A[i][j - 1], dp[i - 1][j] + B[i - 1][j]});
        }
    }
}
int main()
{
    FAST;
    // freopen("input1.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    /*ll tests;
    cin>>tests;
    rep (gg,0,tests)
    {}*/
    ll r, c;
    cin >> r >> c;
    ve<ve<ll>> A(r + 1, ve<ll>(c + 1)), B(r + 1, ve<ll>(c + 1));
    rep(i, 1, r + 1)
    {
        rep(j, 1, c)
        {
            cin >> A[i][j];
        }
    }
    rep(i, 1, r)
    {
        rep(j, 1, c + 1)
        {
            cin >> B[i][j];
        }
    }
    ve<ve<ll>> dp(r + 1, ve<ll>(c + 1, 1e18));
    solve_dp(dp, r, c, A, B);
    rep(z, 0, 1001)
    {
        rep(i, 1, r + 1)
        {
            rev (j, c+1, 2)
            {
                dp[i][j - 1] = min(dp[i][j - 1], dp[i][j] + A[i][j - 1]);
            }
        }
        ve<ll> mn(c + 1, 1e18);
        rev(i, r + 1, 1)
        {
            rep(j, 1, c + 1)
            {
                mn[j] = min(mn[j], dp[i][j] + i + 1);
            }
            rep(j, 1, c + 1)
            {
                dp[i][j] = min(dp[i][j], mn[j] - i);
            }
        }
        solve_dp(dp, r, c, A, B);
    }
    cout << dp[r][c] << "\n";
}
