#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>

namespace detail
{
    template< typename T, std::size_t NDIMS > struct vector_builder
    {
        using type = std::vector< typename vector_builder<T,NDIMS-1>::type > ;

        static type make( std::vector<std::size_t> dims, const T& v = {} )
        {
            const auto vec = std::vector<T>( dims.empty() ? 0 : dims.back(), v ) ;
            if( !dims.empty() ) dims.pop_back() ;
            return vector_builder< std::vector<T>, NDIMS-1 >::make( dims, vec ) ;
        }
    };

    template< typename T > struct vector_builder<T,1>
    {
        using type = std::vector<T> ;

        static type make( std::vector<std::size_t> dims, const T& v = {} )
        { return type( dims.empty() ? 0 : dims.back(), v ) ; }
    };
}



template< typename T, typename... SIZE_T >
auto exvector( const T& v, SIZE_T... dims )
{
    static_assert( sizeof...(dims) != 0, "invalid dimension" ) ;
    std::vector<std::size_t> vec_dims{ dims... } ;
    return detail::vector_builder< T, sizeof...(dims) >::make( vec_dims, v ) ;
}


using namespace std;
//********************  dumps ************************//

template<typename T>
void dump(const T& data, vector<int>& iter) {
    cout << data << " ";
}
template<typename T>
void dump(const vector<T>& data, vector<int>& iter) {
    for(auto elem: data)
        dump(elem, iter);
    cout << endl;
}

template<typename T>
void dump(const vector<vector<T>>& data, vector<int>& iter) {
    for(auto elem : iter) {
        cout << "[" << elem << "]" ;
    }
    cout << endl;
    for(int i=0; i<data.size(); i++) {
        iter.push_back(i);
        dump(data[i], iter);
        iter.pop_back();
    }
    cout << endl;
}

template<typename T>
void dump(const vector<T>& data, int dummy) {
    for(int i=0; i<data.size(); i++) {
        cout <<"[" << i << "] " <<  data[i] << endl;
    }
}
template<typename T>
void dump(const T& data) { // T : data, U = base type val.
    vector<int> iter;
    dump(data, iter);
}

// ===================================
// getter / setter

template<typename T, typename U>
void setval(T& container, vector<int>& pos, U val, int iter) {
    container = (T)val;
}

template<typename T, typename U>
void setval(vector<T>& container, vector<int>& pos, U val, int iter) {
    setval(container[pos[iter]], pos, val, iter+1);
}
/*
template<typename T, typename U>
void setval(T& container, vector<int>& pos,  U val) {
    int iter = 0;
    setval(container, pos, val, iter);    
}
*/
template<typename T, typename U>
void setval(T& container, vector<int> pos,  U val) {
    int iter = 0;
    setval(container, pos, val, iter);    
}

template<typename T>
T getval(T& container, vector<int>& pos, T tmp,int iter) {
    return tmp = container;
}

template<typename T, typename U>
U getval(vector<T>& container, vector<int>& pos, U tmp, int iter) {
    return getval(container[pos[iter]], pos, tmp, iter+1);
}

template<typename T, typename U>
U getval(T& container, vector<int> pos, U& tmp) {
    int iter = 0;
    return getval(container, pos, tmp, iter);    
}





#include<functional>

vector<vector<int>> update_dp(
        vector<int> base_vector, 
        int iter,
        int initial_value,
        function<int(int, int)> op_merge,
        function<vector<int>(int)> update_pos,
        function<int(int, vector<int>& , vector<int>&)> op_edge
         ) {
    vector<vector<int>> result;
    result.push_back(base_vector);
    for(int i=0; i<iter; i++) {
        vector<int>& prev_table = result.back();
        vector<int> current(base_vector.size(), initial_value);
        for(int j=0; j<current.size(); j++) {
            vector<int> prev = update_pos(j);
            for(int k=0; k<prev.size(); k++) {
                vector<int> prev_ind = {i, prev[k]};
                vector<int> next_ind = {i+1, j };

                current[j] = op_merge(current[j], 
                    op_edge(prev_table[prev[k]]
                    , prev_ind, next_ind));
            }
        }
        result.push_back(current);
    }
    return result;
    
} 

int main() {
    auto base_vector = exvector((int)0, 3);

    int N;
    cin >> N;
    auto input = exvector((int)0, N, 3);
    for(int i=0; i<N; i++) {
        for(int j=0; j<3; j++)
            cin >> input[i][j];

    }

    int iter = N;
    function<int(int, int)> op_merge = [] (int a, int b)-> int{
        return max(a, b);
    };
    function<vector<int>(int)> update_pos = [](int a) -> vector<int>{
        vector<int> ret;
        for(int i=0; i<3; i++)
            if(a != i) 
                ret.push_back(i);
        return ret;
    };
    int tmp_for_template;
    function<int(int, vector<int>&, vector<int>&)> op_edge = 
            [&](int val, vector<int>& from, vector<int>& to) -> int{
        to[0]--;
        return val + getval(input, to, tmp_for_template);

    };
    auto result = update_dp(
        vector<int> (3, 0),
        N, 0,
        op_merge, update_pos, op_edge
    );
    cout << max({result[N][0], result[N][1], result[N][2]});

    return 0;
}

Measured memory_bytes: 12212