#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <queue>
#include <deque>
#include <stack>
#include <fstream>
#include <cmath>
#include <random>
#include <complex>
#include <functional>
#include <bitset>
#include <sstream>
#include <cassert>
#include <time.h>

#define ll int64_t
#define Rep(i, n) for (ll i = 0; i < n; i++)
using namespace std;
typedef vector<ll> vec;
typedef vector<vec> mat;

const ll inf = 1LL << 60;

template<class T> inline void chmin(T& a, T b) {
    if (a > b) {
        a = b;
    }
}
template<class T> inline void chmax(T& a, T b) {
    if (a < b) {
        a = b;
    }
}
void printvec (vec &v) {
    Rep (i, (ll)v.size()) {
        cout << v[i] << " \n"[i+1 == (ll)v.size()];
    }
}

class edge {
    public:
    ll from;
    ll to;
    ll cost = 1;

    edge (ll from, ll to) : from(from), to(to) {}
    edge (ll from, ll to, ll cost) : from(from), to(to), cost(cost) {}
};

class graph {
    public:
    ll n;
    ll m;
    
    vector<vector<edge>> g;
    vec d;
    vec prev;

    graph (ll n, ll m) : n(n), m(m) {
        g.assign(n, vector<edge>());
        d.assign(n, inf);
        prev.assign(n, -1);
    }

    void add_edge (ll u, ll v) {
        edge e(u, v);
        g[u].push_back(e);
    }

    void add_edge (ll u, ll v, ll c) {
        edge e(u, v, c);
        g[u].push_back(e);
    }

    vec dijkstra (ll s) {
        priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> pq;
        vec d(n, inf);
        d[s] = 0;
        pq.push({0, s});

        while (pq.size()) {
            auto p = pq.top();
            pq.pop();
            ll v = p.second;
            if (d[v] < p.first) continue;
            for (edge e : g[v]) {
                if (d[e.to] > d[v] + e.cost) {
                    d[e.to] = d[v] + e.cost;
                    prev[e.to] = v;
                    pq.push({d[e.to], e.to});
                }
            }
        }

        return d;
    }

    vec shortest_path (ll s, ll t) {
        vec d = dijkstra(s);
        vec ret;
        if (d[t] == inf) {
            return ret;
        }
        ret.push_back(t);
        ll now = t;
        while (now != s) {
            ret.push_back(prev[now]);
            now = prev[now];
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
};

ll R, C, K;

ll encode (ll num, ll r, ll c) {
    return num + (r * (C+1) + c) * 4;
}

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

    cin >> R >> C >> K;

    mat items(R, vec(C, 0));
    Rep (i, K) {
        ll r, c, v;
        cin >> r >> c >> v;
        r--; c--;
        items[r][c] = v;
    }

    vector<mat> dp(4, mat(R+1, vec(C+1, 0)));

    Rep (j, R+1) {
        Rep (k, C+1) {
            Rep (i, 4) {
                if (k+1 < C+1) {
                    if (i+1 < 4 and j < R and k < C) {
                        chmax(dp[i+1][j][k+1], dp[i][j][k] + items[j][k]);
                    }
                    chmax(dp[i][j][k+1], dp[i][j][k]);
                }

                if (j+1 < R+1) {
                    if (i+1 < 4 and j < R and k < C) {
                        chmax(dp[0][j+1][k], dp[i][j][k] + items[j][k]);
                    }
                    chmax(dp[0][j+1][k], dp[i][j][k]);
                }
            }
        }
    }

    // Rep (i, 4) {
    //     cout << "\n";
    //     Rep (j, R+1) {
    //         Rep (k, C+1) {
    //             cout << dp[i][j][k] << " \n"[k+1==C+1];
    //         }
    //     }
    // }

    ll ans = 0;
    Rep (i, 4) {
        chmax(ans, dp[i][R][C]);
    }

    cout << ans << endl;
}

Measured memory_bytes: 425820