// #include <bits/stdc++.h>

// using namespace std;

// #define lli long long
// #define ld long double
// #define mod 1000000007 
// #define set(n) cout << fixed << setprecision(n)    
// #define fi first
// #define se second
// #define mp make_pair
// #define pll pair<lli, lli>
// #define endl '\n'

// const double PI = acos(-1);
// const double epsilon = 1e-7;  // floating point precision

// class segTreeNode {
// public :
//     /* Class Data Members */
//     lli mx, mn, l, r, diff, sum;
//     /* This node is a class implementing the following methods: 
//     * constructor: identity element of monoid (you should have the neutral values)
//     * constructor: element created by combining 2 elements
//     */
//     segTreeNode() {
//         mx = -1e18, mn = 1e18;
//         diff = 0ll;
//         l = -1, r = -1; sum = 0ll;
//     }
//     segTreeNode(const segTreeNode& one, const segTreeNode& two) {
//         mx = max(one.mx, two.mx);
//         mn = min(one.mn, two.mn);
//         l = one.l, r = two.r;
//         if(l == -1) l = two.l;
//         if(r == -1) r = one.r;
//         diff = one.diff + two.diff;
//         sum = one.sum + two.sum;
//     }  
// };

// class Function {
// public :
//     /* Function Data Members */
//     lli a, b;
//     /* A Function is a class implementing the following methods: 
//     * constructor: identity function
//     * constructor : to construct arbitrary function
//     * constructor: function composition (f1.f2)
//     * whether this function is the identity function
//     * function definition (action on segTreeNode)
//     */
//     Function() {
//         a = 1, b = 0;
//     }
//     Function(lli a, lli b) : a(a), b(b) {

//     }
//     Function(const Function& f1, const Function& f2) {
//         a = f1.a * f2.a;
//         b = f1.a * f2.b + f1.b;
//     }  
//     bool is_identity() const {
//         return a == 1 and b == 0;
//     }  
//     segTreeNode operator()(const segTreeNode& node) {
//         segTreeNode ans = node;
//         ans.mn = a * node.mn + b;
//         ans.mx = a * node.mx + b;
//         ans.sum = node.diff * b + a * node.sum;
//         return ans;
//     }  

// };

// template<class M, class F>
// class SegTree {
// // M is a node
// // F is a function
// // remember to set leaf nodes from calling function with diff = 1
// public:
//     typedef M value_type;
//     typedef F func_type;

//     static void identity_check() {
//         if(!F().is_identity()) {
//             cout << "Default Constructor is not identity !!!" << endl;
//         }
//     }

// private:
//     lli n;
//     vector<M> values;  // the segment tree
//     vector<F> pends;   // stores pending updates for lazy propogation

//     lli segtree_size(lli n) {
//         n -= 1;
//         n |= n >> 1;
//         n |= n >> 2;
//         n |= n >> 4;
//         n |= n >> 8;
//         n |= n >> 16;
//         return 2 * n + 1;
//     }

// public:
//     explicit SegTree(lli N):
//         n(N), values(segtree_size(n)), pends(values.size()) {identity_check();}  // creates empty segment tree
//     explicit SegTree(lli N, const M& x):
//         n(N), values(segtree_size(n)), pends(values.size()) {identity_check(); assign(x);}  // segment tree with fixed leaf values 
//     explicit SegTree(std::vector<M>& v):
//         n(v.size()), values(segtree_size(v.size())), pends(values.size()) {identity_check(); assign(v);}

// private:
//     // build function with vector of leaves 
//     void assign_values(lli root, lli first, lli last, vector<M> &a) {
//         // root has the node number, first and last have the array indices.
//         if(first == last) {
//             values[root] = a[first];
//         }
//         else {
//             lli left = 2 * root + 1;
//             lli mid = (first + last) / 2;
//             assign_values(left, first, mid, a);
//             assign_values(left + 1, mid + 1, last, a);
//             values[root] = M(values[left], values[left + 1]);
//         }
//     }

//     // build function with every leaf assigned x
//     void assign_values(lli root, lli first, lli last, M& x) {
//         // root has the node number, first and last have the array indices.
//         if(first == last) {
//             values[root] = x;
//         }
//         else {
//             lli left = 2 * root + 1;
//             lli mid = (first + last) / 2;
//             assign_values(left, first, mid, x);
//             assign_values(left + 1, mid + 1, last, x);
//             values[root] = M(values[left], values[left + 1]);
//         }
//     }

// public:
//     // assign every leaf x
//     void assign(M& x) {
//         pends.assign(values.size(), F());
//         assign_values(0, 0, n - 1, x);
//     }

//     // assign every leaf corresponding vector entry
//     void assign(vector<M>& v) {
//         if(v.size() < n) {
//             std::exit(3);
//         }
//         assign_values(0, 0, n - 1, v);
//     }

// private:
//     // lazy propagation
//     void propagate(lli root, lli first, lli last) {
//         if(!pends[root].is_identity()) {
//             values[root] = pends[root](values[root]);
//             if(first != last)
//             {
//                 lli left = 2 * root + 1;
//                 pends[left] = F(pends[root], pends[left]);
//                 pends[left + 1] = F(pends[root], pends[left + 1]);
//             }
//             pends[root] = F();
//         }
//     }
//     // query from range l to r (zero indexing)
//     M query(lli root, lli first, lli last, lli l, lli r) {
//         if(l > last or r < first) {
//             return M();
//         }
//         propagate(root, first, last);
//         if(l <= first and last <= r) {
//             return values[root];
//         }
//         else {
//             lli left = 2 * root + 1;
//             lli mid = (first + last) / 2;
//             return M(query(left, first, mid, l, r), query(left + 1, mid + 1, last, l, r));
//         }
//     }

// public:
//     // query from range l to r (zero indexing)
//     M query(lli l, lli r) {
//         return query(0, 0, n - 1, l, r);
//     }

// private:
//     // update from range l to r by giving update function (zero indexing)
//     void update(lli root, lli first, lli last, lli l, lli r, const F& f) {
//         if(l > last or r < first) {
//             propagate(root, first, last);
//         }
//         else if(l <= first and last <= r) {
//             pends[root] = F(f, pends[root]);
//             propagate(root, first, last);
//         }
//         else {
//             propagate(root, first, last);
//             lli left = 2 * root + 1;
//             lli mid = (first + last) / 2;
//             update(left, first, mid, l, r, f);
//             update(left + 1, mid + 1, last, l, r, f);
//             values[root] = M(values[left], values[left + 1]);
//         }
//     }

// public:
//     // update from range l to r by giving update function (zero indexing)
//     void update(lli l, lli r, const F& f) {
//         update(0, 0, n - 1, l, r, f);
//     }
// };

// class PNC {
//     public :
//         vector<unsigned lli> f;
//         lli m;
//         PNC(lli n, lli m = mod) {
//             f.resize(n + 1);  this-> m = m; f[0] = 1;
//             for(int i = 1; i <= n; i++) {
//                 f[i] = (i * f[i - 1]) % m;
//             }
//         }
//         lli power(lli b, lli p, lli m = mod){
//             lli res = 1;
//             while(p > 0){
//                 if(p & 1)
//                     res = (res % m * b % m) % m;
//                 b = (b % m * b % m) % m; p = p>>1;
//             }
//             return res;
//         }
//         lli modInverse(lli n, lli m = mod) { return power(n, m - 2, m); }
//         lli factorial(lli n) { return f[n]; }
//         lli nCr(lli n, lli r) { 
//             if(r == 0) return 1;
//             return (f[n] * modInverse(f[r], m) % m * modInverse(f[n - r], m) % m) % m;
//         }
//         lli nPr(lli n, lli r) {
//             if(r == 0) return 1;
//             return (f[n] * modInverse(f[n - r], m) % m) % m;
//         }
// };

// signed main(void) {
//     ios_base::sync_with_stdio(false);
//     cin.tie(NULL);
//     lli t;
//     cin >> t;
//     PNC pnc(5e5 + 5);
//     while(t --> 0) {
//         lli n;
//         cin >> n;
//         vector<lli> a(n);
//         map<lli, lli> cnt;
//         for(int i = 0; i < n; i++) {
//             cin >> a[i];
//             cnt[a[i]] ++;
//         }
//         sort(a.begin(), a.end());
//         a.resize(unique(a.begin(), a.end()) - a.begin());
//         vector<segTreeNode> leaf(n + 1);
//         for(int i = 0; i <= n; i++) {
//             leaf[i].l = leaf[i].r = i;
//             leaf[i].mn = leaf[i].mx = 0;
//             leaf[i].diff = 1;
//         }
//         SegTree<segTreeNode, Function> dp(leaf);
//         vector<vector<lli>> ans(n + 1);
//         for(int i = 1; i <= n; i++) {
//             ans[i].resize(cnt[i] + 1);
//         }
//         for(int i = a.size() - 1; i >= 0; i--) {
//             lli lim = cnt[a[i]];
//             vector<lli> new_dp(lim + 1);
//             for(int j = 1; j <= lim; j++) {
//                 new_dp[j] = pnc.nCr(lim, j) * (1 + dp.query(j, j).mx);
//                 ans[a[i]][j] = new_dp[j];
//             }
//             vector<lli> sum(lim + 1, 1);
//             lli val = 1ll;
//             for(int j = 1; j <= lim; j++) {
//                 val *= (lim - j + 1);
//                 val /= j;
//                 sum[j] = sum[j - 1] + val;
//             }
//             for(int j = 1; j <= lim; j++) {
//                 dp.update(j, j, Function(sum[j], sum[j] - 1));
//             }
//             if(lim + 1 <= n) {
//                 dp.update(lim + 1, n, Function(sum[lim], sum[lim] - 1));
//             }
//         }
//         dp.assign(leaf);
//         for(int i = 0; i < a.size(); i++) {
//             lli lim = cnt[a[i]];
//             for(int j = 1; j <= lim; j++) {
//                 ans[a[i]][j] *= (1 + dp.query(j - 1, j - 1).mx);
//             }
//             vector<lli> sum(lim + 1, 1);
//             lli val = 1ll;
//             for(int j = 1; j <= lim; j++) {
//                 val *= (lim - j + 1);
//                 val /= j;
//                 sum[j] = sum[j - 1] + val;
//             }
//             for(int j = 1; j <= lim; j++) {
//                 dp.update(j, j, Function(sum[j], sum[j] - 1));
//             }
//             if(lim + 1 <= n) {
//                 dp.update(lim + 1, n, Function(sum[lim], sum[lim] - 1));
//             }
//         }
//         for(int i = 1; i <= n; i++) {
//             lli total = 0ll;
//             for(int j = 1; j <= cnt[i]; j++) {
//                 total += ans[i][j];
//             }
//             cout << total << ' ';
//         }
//         cout << endl;
//     }
// }


// #include <bits/stdc++.h>

// using namespace std;

// #define lli long long
// #define ld long double
// #define mod 1000000007 
// #define set(n) cout << fixed << setprecision(n)    
// #define fi first
// #define se second
// #define mp make_pair
// #define pll pair<lli, lli>
// #define endl '\n'

// const double PI = acos(-1);
// const double epsilon = 1e-7;  // floating point precision

// class PNC {
//     public :
//         vector<unsigned lli> f;
//         lli m;
//         PNC(lli n, lli m = mod) {
//             f.resize(n + 1);  this-> m = m; f[0] = 1;
//             for(int i = 1; i <= n; i++) {
//                 f[i] = (i * f[i - 1]) % m;
//             }
//         }
//         lli power(lli b, lli p, lli m = mod){
//             lli res = 1;
//             while(p > 0){
//                 if(p & 1)
//                     res = (res % m * b % m) % m;
//                 b = (b % m * b % m) % m; p = p>>1;
//             }
//             return res;
//         }
//         lli modInverse(lli n, lli m = mod) { return power(n, m - 2, m); }
//         lli factorial(lli n) { return f[n]; }
//         lli nCr(lli n, lli r) { 
//             if(r == 0) return 1;
//             return (f[n] * modInverse(f[r], m) % m * modInverse(f[n - r], m) % m) % m;
//         }
//         lli nPr(lli n, lli r) {
//             if(r == 0) return 1;
//             return (f[n] * modInverse(f[n - r], m) % m) % m;
//         }
// };

// signed main(void) {
//     ios_base::sync_with_stdio(false);
//     cin.tie(NULL);
//     lli t;
//     cin >> t;
//     PNC pnc(5e5 + 5);
//     while(t --> 0) {
//         lli n;
//         cin >> n;
//         vector<lli> a(n);
//         map<lli, lli> cnt;
//         for(int i = 0; i < n; i++) {
//             cin >> a[i];
//             cnt[a[i]] ++;
//         }
//         vector<lli> dp(n + 1);
//         sort(a.begin(), a.end());
//         a.resize(unique(a.begin(), a.end()) - a.begin());
//         int prev_size = n ;
//         vector<vector<lli>> ans(n + 1);
//         for(int i = 1; i <= n; i++) {
//             ans[i].resize(cnt[i] + 1);
//         }
//         for(int i = a.size() - 1; i >= 0; i--) {
//             lli lim = cnt[a[i]];
//             vector<lli> new_dp(lim + 1);
//             for(int j = 1; j <= lim; j++) {
//                 new_dp[j] = pnc.nCr(lim, j) * (1 + dp[j]);
//                 ans[a[i]][j] = new_dp[j];
//             }
//             vector<lli> sum(lim + 1, 1);
//             lli val = 1ll;
//             for(int j = 1; j <= lim; j++) {
//                 val *= (lim - j + 1);
//                 val /= j;
//                 sum[j] = sum[j - 1] + val;
//             }
//             for(int j = 1; j <= n; j++) {
//                 dp[j] = dp[j] * sum[min(lim, (lli)j)] + sum[min(lim, (lli)j)] - 1;
//             }
//             prev_size = lim;
//         }
//         prev_size = n;
//         dp.assign(n + 1, 0);
//         for(int i = 0; i < a.size(); i++) {
//             lli lim = cnt[a[i]];
//             vector<lli> new_dp(lim + 1);
//             for(int j = 1; j <= lim; j++) {
//                 new_dp[j] = pnc.nCr(lim, j) * (1 + dp[j - 1]);
//                 ans[a[i]][j] *= (1 + dp[j - 1]);
//             }
//             vector<lli> sum(lim + 1, 1);
//             lli val = 1ll;
//             for(int j = 1; j <= lim; j++) {
//                 val *= (lim - j + 1);
//                 val /= j;
//                 sum[j] = sum[j - 1] + val;
//             }
//             for(int j = 1; j <= n; j++) {
//                 dp[j] = sum[min(lim, (lli)j)] * dp[j] + sum[min(lim, (lli)j)] - 1;
//             }
//             prev_size = lim;
//         }
//         for(int i = 1; i <= n; i++) {
//             lli total = 0ll;
//             for(int j = 1; j <= cnt[i]; j++) {
//                 total += ans[i][j];
//             }
//             cout << total << ' ';
//         }
//         cout << endl;
//     }
// }   

#include <bits/stdc++.h>

using namespace std;

#define lli long long
#define ld long double
#define mod 1000000007 
#define set(n) cout << fixed << setprecision(n)    
#define fi first
#define se second
#define mp make_pair
#define pll pair<lli, lli>
#define endl '\n'

const double PI = acos(-1);
const double epsilon = 1e-7;  // floating point precision

lli dp[3001][3001][4];

lli solve(lli x, lli y, vector<vector<lli>>& grid, lli r, lli c, lli num) {
    if(x < 0 or y < 0 or x >= r or y >= c) {
        return 0;
    }
    if(dp[x][y][num] >= 0) {
        return dp[x][y][num];
    }
    lli op1 = 0, op2 = 0, op3 = 0, op4 = 0;
    if(grid[x][y] > 0 and num <= 2) {
        op1 = grid[x][y] + solve(x + 1, y, grid, r, c, 0);
        op2 = grid[x][y] + solve(x, y + 1, grid, r, c, num + 1);
    }
    op3 = solve(x + 1, y, grid, r, c, 0);
    op4 = solve(x, y + 1, grid, r, c, num);
    return dp[x][y][num] = max({op1, op2, op3, op4});
}

signed main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    lli r, c, k;
    cin >> r >> c >> k;
    vector<vector<lli>> v(r, vector<lli>(c));
    for(int i = 0; i < k; i++) {
        lli x, y, w;
        cin >> x >> y >> w;
        --x, --y;
        v[x][y] = w;
    }
    memset(dp, -1, sizeof dp);
    cout << solve(0, 0, v, r, c, 0) << endl;
}


Measured memory_bytes: 355880