using System;
using System.Collections;
using System.Collections.Generic;
//using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Math;
using static Math2;
using static Output;
using static Utils;

public class CP
{
	Scan sc;
	public void Solve()
	{
		sc = new Scan();
		bool multicases = false;
		var t = multicases ? sc.Int : 1;
		// var sw = new Stopwatch();
		// sw.Start();
		while (t-- > 0)
		{
			c1();
		}
		// sw.Stop();
		//Put(sw.ElapsedMilliseconds + "ms");
	}
	public void c1()
	{
		int r = sc.Int;
		int c = sc.Int;
		int k = sc.Int;
		long[][] grid = Enumerable.Range(0, r).Select(_ => new long[c]).ToArray();
		for (int i = 0; i < k; ++i)
		{
			var rr = sc.Int - 1;
			var cc = sc.Int - 1;
			var vv = sc.Long;
			grid[rr][cc] = vv;
		}
		var dp = Enumerable.Range(0, r).Select(_ => Enumerable.Range(0, c).Select(__ => new long[4]).ToArray()).ToArray();
		dp[0][0][0] = 0;
		dp[0][0][1] = grid[0][0];
		for (int i = 0; i < r; ++i)
		{
			for (int j = 0; j < c; ++j)
			{
				for (int l = 0; l < 3; ++l)
				{
					//とる
					if (j != 0) dp[i][j][l + 1] = Max(dp[i][j][l + 1], dp[i][j - 1][l] + grid[i][j]);
				}
				for (int l = 0; l < 4; ++l)
				{
					if (i != 0) dp[i][j][1] = Max(dp[i][j][1], dp[i - 1][j][l] + grid[i][j]);
					//取らない
					if (i != 0) dp[i][j][0] = Max(dp[i][j][0], dp[i - 1][j][l]);
					if (j != 0) dp[i][j][l] = Max(dp[i][j][l], dp[i][j - 1][l]);
				}
			}
		}
		long ans = 0;
		ans = Max(ans, dp[r - 1][c - 1][0]);
		ans = Max(ans, dp[r - 1][c - 1][1]);
		ans = Max(ans, dp[r - 1][c - 1][2]);
		ans = Max(ans, dp[r - 1][c - 1][3]);
		Put(ans);
	}

}





public class PriorityQueue<T>
{
	List<T> _item;
	public int Count { get { return _item.Count; } }
	bool _isascend { get; set; }
	public T Peek { get { return _item[0]; } }
	Comparison<T> Comp;
	public PriorityQueue(bool IsAscend = true, IEnumerable<T> list = null) : this(Comparer<T>.Default.Compare, IsAscend, list) { }
	public PriorityQueue(Comparison<T> cmp, bool IsAscend = true, IEnumerable<T> list = null)
	{
		_item = new List<T>();
		_isascend = IsAscend;
		this.Comp = cmp;
		if (list != null)
		{
			_item.AddRange(list);
			Build();
		}
	}

	private int Compare(int i, int j) => (_isascend ? -1 : 1) * Comp(_item[i], _item[j]);
	private void Swap(int i, int j) { var t = _item[i]; _item[i] = _item[j]; _item[j] = t; }
	private int Parent(int i) => (i - 1) >> 1;
	private int Left(int i) => (i << 1) + 1;
	public T Enqueue(T val)
	{
		int i = _item.Count;
		_item.Add(val);
		while (i > 0)
		{
			int p = Parent(i);
			if (Compare(i, p) > 0)
				Swap(i, p);
			i = p;
		}
		return val;
	}
	private void Heapify(int index)
	{
		for (int i = index, j;
				(j = Left(i)) < _item.Count; i = j)
		{
			if (j != _item.Count - 1 && Compare(j, j + 1) < 0) j++;
			if (Compare(i, j) < 0)
				Swap(i, j);
		}
	}
	public T Dequeue()
	{
		T val = _item[0];
		_item[0] = _item[_item.Count - 1];
		_item.RemoveAt(_item.Count - 1);
		Heapify(0);
		return val;
	}
	private void Build()
	{
		for (var i = (_item.Count >> 1) - 1; i >= 0; i--)
			Heapify(i);
	}
	public bool Any() => Count > 0;
}
public class BinarySearch
{
	public static int Lower_Bound<T>(IList<T> Array, T Target)
	{
		return Lower_Bound<T>(Array, Target, Comparer<T>.Default.Compare);
	}
	public static int Lower_Bound<T>(IList<T> Array, T Target, Comparison<T> Comp)
	{
		var cmp = Comparer<T>.Create(Comp);
		var l = -1; //always ng
		var r = Array.Count(); //always ok
		while (r - l > 1)
		{
			var mid = l + (r - l) / 2;
			var res = cmp.Compare(Array[mid], Target);
			if (res >= 0) r = mid;
			else l = mid;
		}
		return r;
	}
	public static int Upper_Bound<T>(IList<T> Array, T Target)
	{
		return Upper_Bound<T>(Array, Target, Comparer<T>.Default.Compare);
	}
	public static int Upper_Bound<T>(IList<T> Array, T Target, Comparison<T> Comp)
	{
		var cmp = Comparer<T>.Create(Comp);
		var l = -1;
		var r = Array.Count;
		while (r - l > 1)
		{
			var mid = l + (r - l) / 2;
			var res = cmp.Compare(Array[mid], Target);
			if (res > 0) r = mid;
			else l = mid;
		}
		return r;
	}
	public static bool Contains<T>(IList<T> Arr, T Target)
	{
		return Contains<T>(Arr, Target, Comparer<T>.Default.Compare);
	}
	public static bool Contains<T>(IList<T> Arr, T Target, Comparison<T> Comp)
	{
		return (Upper_Bound(Arr, Target, Comp) - Lower_Bound(Arr, Target, Comp) > 0);
	}
}
public static class Math2
{
	public const int INF = 1 << 29;
	public const long INFL = 1L << 62;
	public const long MOD = 1000000007;
	public const long MOD2 = 998244353;

	public static long Power(long a, long b, long MOD = 1000000007) //i^N
	{
		long res = 1;
		while (b > 0)
		{
			if ((b & 1) != 0) res = res * a % MOD;
			a = a * a % MOD;
			b >>= 1;
		}
		return (res + 2 * MOD) % MOD;
	}
	public static long Power2(long a, long b) //i^N
	{
		long res = 1;
		while (b > 0)
		{
			if ((b & 1) != 0) res = res * a;
			a = a * a;
			b >>= 1;
		}
		return res;
	}
	public static BigInteger Power2BI(BigInteger a, BigInteger b) //i^N
	{
		BigInteger res = 1;
		while (b > 0)
		{
			if ((b & 1) != 0) res = res * a;
			a = a * a;
			b >>= 1;
		}
		return res;
	}
	public static long GCD(long a, long b)
	{
		if (a == 0) return b;
		while (b > 0)
		{
			var r = a % b;
			a = b;
			b = r;
		}
		return a;
	}
	public static long LCM(long a, long b) => (b / GCD(a, b)) * a;
	public static long Comb(long n, long r, int MOD = 1000000007)
	{
		if (r > n - r) r = n - r;
		long Nume = 1;
		long Deno = 1;

		if (r > n - r) r = n - r;
		for (long i = 1; i <= r; ++i)
		{
			Deno = (Deno * i) % MOD;
			Nume = Nume * (n - i + 1) % MOD;
		}
		return (Nume * inv(Deno)) % MOD;
	}
	public static long Comb2(long n, long r)
	{
		long Nume = 1;
		long Deno = 1;

		if (r > n - r) r = n - r;
		for (long i = 1; i <= r; ++i)
		{
			Deno *= i;
			Nume *= n - i + 1;
		}
		return Nume / Deno;
	}
	public static long inv(long x, int MOD = 1000000007)
	{
		return Power(x, MOD - 2, MOD);
	}
}
public static class Utils
{
	public static T[] sort<T>(this T[] a)
	{
		Array.Sort(a);
		return a;
	}
	public static long popcnt(long n)
	{
		n = (n & 0x55555555) + (n >> 1 & 0x55555555);
		n = (n & 0x33333333) + (n >> 2 & 0x33333333);
		n = (n & 0x0f0f0f0f) + (n >> 4 & 0x0f0f0f0f);
		n = (n & 0x00ff00ff) + (n >> 8 & 0x00ff00ff);
		n = (n & 0x0000ffff) + (n >> 16 & 0x0000ffff);
		return n;
	}
	public static int popcnt(BigInteger a)
	{
		int cnt = 0;
		while (a > 0)
		{
			if ((a & 1) == 1) ++cnt;
			a >>= 1;
		}
		return cnt;
	}
	public static void Swap<T>(ref T A, ref T B)
	{
		T x = A;
		A = B;
		B = x;
	}
	public static int DigitSum(string N)
	{

		int ret = 0;
		for (int i = 0; i < N.Length; ++i) ret += N[i] - '0';
		return ret;
	}
	public static string ConvertBase(char[] Num, int from, int to)
	{
		if (new string(Num) == "0") return "0";
		char[] sample = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
		BigInteger ten = 0;
		int power = 0;
		for (int i = Num.Length - 1; i >= 0; --i)
		{
			ten += (BigInteger)(Array.IndexOf(sample, Num[i])) * Power2BI(from, power);
			++power;
		}
		if (to == 10)
		{
			return ten.ToString();
		}
		var ret = new List<char>();
		if (to > 0)
		{
			while (ten > 0)
			{
				int r = (int)(ten % (to));
				ret.Add(sample[r]);
				ten /= to;
			}
		}
		else
		{
			while (ten != 0)
			{
				var r = (int)(ten % -to);
				if (r < 0) r -= to;
				ret.Add(sample[r]);
				ten -= r;
				ten /= -to;
				ten *= -1;
			}
		}
		ret.Reverse();
		return new string(ret.ToArray());
	}
	public static bool NextPermutation<T>(IList<T> lis, Comparison<T> cmp)
	{
		int n = lis.Count;
		int i = n - 1;
		while (i - 1 >= 0)
		{
			if (cmp(lis[i - 1], lis[i]) < 0) break;
			--i;
		}
		if (i == 0) return false;
		int j = i;
		while (j + 1 < n)
		{
			if (cmp(lis[i - 1], lis[j + 1]) > 0) break;
			++j;
		}
		var _q = lis[j];
		lis[j] = lis[i - 1];
		lis[i - 1] = _q;
		int k = i;
		int l = n - 1;
		while (k < l)
		{
			var _p = lis[k];
			lis[k] = lis[l];
			lis[l] = _p;

			++k;
			--l;
		}
		return true;
	}
	public static bool NextPermutation<T>(IList<T> lis) => NextPermutation(lis, Comparer<T>.Default.Compare);
}
class Program
{
	static void Main(string[] args)
	{
		var CP = new CP();
		CP.Solve();
	}
}
public static class Output
{

	public static void Put(string a) => Console.WriteLine(a);
	public static void Put(params object[] i) => Put(string.Join(" ", i));
	public static void Put<T>(IEnumerable<T> a) => Put(string.Join(" ", a));
	public static void PutV<T>(IEnumerable<T> a) { foreach (var z in a) Put(z); }
	public static void YN(bool i)
	{
		if (i) Put("Yes");
		else Put("No");
	}
}
public class Scan
{
	public static string Str => Console.ReadLine();
	public static bool IsTypeEqual<T, U>() => typeof(T).Equals(typeof(U));
	public static T ConvertType<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
	public static T Cast<T>(string s)
	{
		if (IsTypeEqual<T, int>()) return ConvertType<T, int>(int.Parse(s));
		else if (IsTypeEqual<T, long>()) return ConvertType<T, long>(long.Parse(s));
		else if (IsTypeEqual<T, double>()) return ConvertType<T, double>(double.Parse(s));
		else if (IsTypeEqual<T, char>()) return ConvertType<T, char>(char.Parse(s));
		else if (IsTypeEqual<T, BigInteger>()) return ConvertType<T, BigInteger>(BigInteger.Parse(s));
		else if (IsTypeEqual<T, decimal>()) return ConvertType<T, decimal>(decimal.Parse(s));
		else return ConvertType<T, string>(s);
	}
	public static T[] Castarr<T>(string[] s)
	{

		var ret = new T[s.Length];
		int i = 0;
		if (IsTypeEqual<T, char>())
		{
			var list = new List<T>();
			foreach (var t in s)
			{
				foreach (var u in t)
				{
					list.Add(ConvertType<T, char>(char.Parse(u.ToString())));
				}
			}
			return list.ToArray();
		}
		foreach (var t in s)
		{
			if (IsTypeEqual<T, int>()) ret[i++] = ConvertType<T, int>(int.Parse(t));
			else if (IsTypeEqual<T, long>()) ret[i++] = ConvertType<T, long>(long.Parse(t));
			else if (IsTypeEqual<T, double>()) ret[i++] = ConvertType<T, double>(double.Parse(t));
			else if (IsTypeEqual<T, BigInteger>()) ret[i++] = ConvertType<T, BigInteger>(BigInteger.Parse(t));
			else ret[i++] = ConvertType<T, string>(t);
		}
		return ret;
	}
	Queue<string> q = new Queue<string>();
	void next() { var ss = Str.Split(' '); foreach (var item in ss) q.Enqueue(item); }
	public T cin<T>() { if (!q.Any()) next(); return Cast<T>(q.Dequeue()); }
	public T[] cinarr<T>() { return Castarr<T>(Str.Split(' ')); }
	public T[] cinarr<T>(int n) { var ret = new T[n]; for (int i = 0; i < n; ++i) ret[i] = cin<T>(); return ret; }
	public int Int => cin<int>();
	public long Long => cin<long>();
	public double Double => cin<double>();
	public char Char => cin<char>();
	public string String => cin<string>();
	public BigInteger BI => cin<BigInteger>();
	public int[] Intarr => cinarr<int>();
	public long[] Longarr => cinarr<long>();
	public double[] Doublearr => cinarr<double>();
	public char[] Chararr => cinarr<char>();
	public string[] Stringarr => cinarr<string>();
	public BigInteger[] BIarr => cinarr<BigInteger>();
	public void cin<T>(out T t) { t = cin<T>(); }
	public void mul<T, U>(out T t, out U u) { t = cin<T>(); u = cin<U>(); }
	public void mul<T, U, V>(out T t, out U u, out V v) { t = cin<T>(); u = cin<U>(); v = cin<V>(); }
	public void mul<T, U, V, W>(out T t, out U u, out V v, out W w) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); }
	public void mul<T, U, V, W, X>(out T t, out U u, out V v, out W w, out X x) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); }
	public void mul<T, U, V, W, X, Y>(out T t, out U u, out V v, out W w, out X x, out Y y) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); y = cin<Y>(); }
	public void mul<T, U, V, W, X, Y, Z>(out T t, out U u, out V v, out W w, out X x, out Y y, out Z z) { t = cin<T>(); u = cin<U>(); v = cin<V>(); w = cin<W>(); x = cin<X>(); y = cin<Y>(); z = cin<Z>(); }
}

Measured memory_bytes: 665468