#include <set>
#include <array>
#include <limits>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <numeric>
#include <tuple>
#include <cassert>
#include <unordered_set>
#include <bitset>
#include <thread>
#include <future>
#include <memory>
#include <map>
#include <unordered_map>
namespace
{
namespace common
{
template<class Func>
void repeat_n(int size, Func func)
{
for(int i=0 ; i < size; ++i)
{
func(i);
}
}
template<class T>
T get(std::istream& stream)
{
T value;
stream >> value;
return value;
}
template<class Func>
void run_test_case(std::istream& stream, Func func)
{
repeat_n(get<int>(stream), [func, &stream](int )
{
func(stream);
});
}
template<class T>
struct optional
{
public:
optional() = default;
optional(T value_) : _value(value_), _has_value(true)
{
}
bool has_value() const
{
return _has_value;
}
const T& value() const
{
return _value;
}
private:
bool _has_value = false;
T _value;
};
template<class Def>
class memoization
{
using key_type = typename Def::key_type;
using value_type = typename Def::value_type;
using this_type = memoization<Def>;
using solve_func = std::function<value_type (const key_type&, this_type&)>;
public:
memoization(solve_func func) : _func(func)
{
}
value_type solve(const key_type& key)
{
auto optional_value = Def::get(_map, key);
if(optional_value.has_value())
{
return optional_value.value();
}
else
{
auto value = _func(key, *this);
return Def::set(_map, key, value);
}
}
private:
solve_func _func;
typename Def::map_type _map;
};
}
struct map_def
{
using map_type = std::unordered_map<int, int>;
using key_type = std::pair<short, short>;
using value_type = int;
union id_type
{
struct
{
short k1;
short k2;
}raw;
int value;
} ;
static common::optional<int> get(const map_type& map_, key_type key)
{
id_type id;
id.raw.k1 = key.first;
id.raw.k2 = key.second;
auto find_value = map_.find(id.value);
if(find_value != map_.end())
{
return common::optional<int>(find_value->second);
}
return common::optional<int>();
}
static value_type set(map_type& map_, key_type key, int value)
{
id_type id;
id.raw.k1 = key.first;
id.raw.k2 = key.second;
map_[id.value] = value;
return value;
}
};
class triangle_path_data
{
public:
static const int max_size = 100;
triangle_path_data() = default;
int size() const
{
return _size;
}
static triangle_path_data create_from_stream(std::istream& stream)
{
triangle_path_data triangle_path_data_;
triangle_path_data_._size = common::get<int>(stream);
common::repeat_n(triangle_path_data_._size, [&](int row_index)
{
common::repeat_n(row_index+1, [&](int column_index)
{
triangle_path_data_._data[row_index][column_index] = common::get<int>(stream);
});
});
return triangle_path_data_;
}
int get(int row, int column)
{
assert(is_valid(row, column));
return _data[row][column];
}
bool is_valid(int row, int column)
{
return row < _size && column <= row;
}
private:
int _size =0;
std::array<std::array<int, 100>, 100> _data;
};
struct triangle_path_solver
{
public:
triangle_path_solver(triangle_path_data& data_) : triangle_data_(data_){}
int solve(const map_def::key_type& key, common::memoization<map_def>& memo) const
{
if(triangle_data_.is_valid(key.first, key.second) == false)
{
return 0;
}
else
{
return triangle_data_.get(key.first, key.second) +
std::max(memo.solve(std::make_pair(key.first+1, key.second)), memo.solve(std::make_pair(key.first+1, key.second+1)));
}
}
private:
triangle_path_data& triangle_data_;
};
}
#ifdef __TEST__
int triangle_path_main()
#else
int main()
#endif
{
common::run_test_case(std::cin, [](std::istream& stream)
{
auto triangle_data_ = triangle_path_data::create_from_stream(stream);
triangle_path_solver solver(triangle_data_);
common::memoization<map_def> memoization_solver([solver](const map_def::key_type& key, common::memoization<map_def>& memo )
{
return solver.solve(key, memo);
});
std::cout << memoization_solver.solve(std::make_pair(0,0)) << std::endl;
});
return 0;
}