#include <bits/stdc++.h>
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#define NDEBUG
#define SHOW(...) static_cast<void>(0)
//!===========================================================!//
//!  dP     dP                          dP                    !//
//!  88     88                          88                    !//
//!  88aaaaa88a .d8888b. .d8888b. .d888b88 .d8888b. 88d888b.  !//
//!  88     88  88ooood8 88'  '88 88'  '88 88ooood8 88'  '88  !//
//!  88     88  88.  ... 88.  .88 88.  .88 88.  ... 88        !//
//!  dP     dP  '88888P' '88888P8 '88888P8 '88888P' dP        !//
//!===========================================================!//
template <typename T, typename A>
std::istream& operator>>(std::istream& is, std::vector<T, A>& v)
{
    for (auto& e : v) { is >> e; }
    return is;
}
template <typename T>
T read()
{
    T v;
    return std::cin >> v, v;
}
template <typename T>
std::vector<T> readVec(const std::size_t l)
{
    std::vector<T> v(l);
    for (auto& e : v) { std::cin >> e; }
    return v;
}
using ld = long double;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr unsigned int MOD = 1000000007;
template <typename T>
constexpr T INF = std::numeric_limits<T>::max() / 4;
template <typename F>
constexpr F PI = static_cast<F>(3.1415926535897932385);
std::mt19937 mt{std::random_device{}()};
template <typename T>
bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template <typename T>
bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
template <typename T>
std::vector<T> Vec(const std::size_t n, T v) { return std::vector<T>(n, v); }
template <class... Args>
auto Vec(const std::size_t n, Args... args) { return std::vector<decltype(Vec(args...))>(n, Vec(args...)); }
template <typename T>
constexpr T popCount(const T u)
{
#ifdef __has_builtin
    return u == 0 ? T(0) : (T)__builtin_popcountll(u);
#else
    unsigned long long v = static_cast<unsigned long long>(u);
    return v = (v & 0x5555555555555555ULL) + (v >> 1 & 0x5555555555555555ULL), v = (v & 0x3333333333333333ULL) + (v >> 2 & 0x3333333333333333ULL), v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL, static_cast<T>(v * 0x0101010101010101ULL >> 56 & 0x7f);
#endif
}
template <typename T>
constexpr T log2p1(const T u)
{
#ifdef __has_builtin
    return u == 0 ? T(0) : T(64 - __builtin_clzll(u));
#else
    unsigned long long v = static_cast<unsigned long long>(u);
    return v = static_cast<unsigned long long>(v), v |= (v >> 1), v |= (v >> 2), v |= (v >> 4), v |= (v >> 8), v |= (v >> 16), v |= (v >> 32), popCount(v);
#endif
}
template <typename T>
constexpr T clog(const T v) { return v == 0 ? T(0) : log2p1(v - 1); }
template <typename T>
constexpr T msbp1(const T v) { return log2p1(v); }
template <typename T>
constexpr T lsbp1(const T v)
{
#ifdef __has_builtin
    return __builtin_ffsll(v);
#else
    return v == 0 ? T(0) : popCount((v & (-v)) - T(1)) + T(1);
#endif
}
template <typename T>
constexpr bool ispow2(const T v) { return popCount(v) == 1; }
template <typename T>
constexpr T ceil2(const T v) { return v == 0 ? T(1) : T(1) << log2p1(v - 1); }
template <typename T>
constexpr T floor2(const T v) { return v == 0 ? T(0) : T(1) << (log2p1(v) - 1); }
//!===========================================================================!//
//!   a88888b.                     dP       88888888b dP                      !//
//!  d8'   '88                     88       88        88                      !//
//!  88        .d8888b. .d8888b. d8888P    a88aaaa    88 .d8888b. dP  dP  dP  !//
//!  88        88'  '88 Y8ooooo.   88       88        88 88'  '88 88  88  88  !//
//!  Y8.   .88 88.  .88       88   88       88        88 88.  .88 88.88b.88'  !//
//!   Y88888P' '88888P' '88888P'   dP       dP        dP '88888P' 8888P Y8P   !//
//!===========================================================================!//
template <typename Cap, typename Cost, typename Ind = std::size_t>
struct CostFlow
{
    CostFlow(const Ind v) : V(v), edge(v) { edge.shrink_to_fit(); }
    void addEdge(const Ind from, const Ind to, const Cap cap, const Cost cost) { assert(from < V), assert(to < V), edge[from].push_back(Edge{to, (Ind)edge[to].size(), cap, cost, false}), edge[to].push_back(Edge{from, (Ind)(edge[from].size() - 1), 0, -cost, true}); }
    struct Edge
    {
        Ind to, rev;
        Cap cap;
        Cost cost;
        const bool isrev;
    };
    const std::vector<Edge>& operator[](const std::size_t i) const { return assert(i < V), edge[i]; }
    friend std::ostream& operator<<(std::ostream& os, const CostFlow& cf)
    {
        os << "[\n";
        for (std::size_t i = 0; i < cf.V; i++) {
            for (const auto& e : cf.edge[i]) {
                if (not e.isrev) { os << i << "->" << e.to << ":"
                                      << "<Cap=" << e.cap << ",Cost=" << e.cost << ">\n"; }
            }
        }
        return (os << "]\n");
    }
    const Ind V;
    std::vector<std::vector<Edge>> edge;
};
//!=====================================================================!//
//!  888888ba             dP      888888ba                              !//
//!  88    '8b            88      88    '8b                             !//
//! a88aaaa8P' .d8888b. d8888P    88     88 .d8888b. 88d888b. .d8888b.  !//
//!  88        88'  '88   88      88     88 88'  '88 88'  '88 88ooood8  !//
//!  88        88.  .88   88      88     88 88.  .88 88    88 88.  ...  !//
//!  dP        '88888P'   dP      dP     dP '88888P' dP    dP '88888P'  !//
//!=====================================================================!//
template <typename T, typename Cap, typename Cost, typename Ind>
struct PotNone
{
    std::vector<T> operator()(const CostFlow<Cap, Cost, Ind>& cflow, const Ind) const
    {
        std::vector<T> ans(cflow.V, 0);
        return ans.shrink_to_fit(), ans;
    }
};
//!==================================================================================!//
//!  888888ba           oo                     dP    888888ba                    dP  !//
//!  88    '8b                                 88    88    '8b                   88  !//
//! a88aaaa8P' 88d888b. dP 88d8b.d8b. .d8888b. 88    88     88 dP    dP .d8888b. 88  !//
//!  88        88'  '88 88 88''88''88 88'  '88 88    88     88 88    88 88'  '88 88  !//
//!  88        88       88 88  88  88 88.  .88 88    88    .8P 88.  .88 88.  .88 88  !//
//!  dP        dP       dP dP  dP  dP '88888P8 dP    8888888P  '88888P' '88888P8 dP  !//
//!==================================================================================!//
template <typename T, template <typename, typename, typename, typename> class PotFunc = PotNone, typename Cap = ll, typename Cost = ll, typename Ind = std::size_t>
std::pair<bool, T> PrimalDual(CostFlow<Cap, Cost, Ind>& cflow, const Ind s, const Ind t, Cap f)
{
    const Ind V = cflow.V;
    T ans = 0;
    std::vector<T> potential = PotFunc<T, Cap, Cost, Ind>()(cflow, s);
    std::vector<T> dist(V, std::numeric_limits<T>::max());
    using P = std::pair<T, Ind>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> Q;
    std::vector<Ind> prev_v(V), prev_e(V);
    dist.shrink_to_fit(), prev_v.shrink_to_fit(), prev_e.shrink_to_fit();
    while (f > 0) {
        std::fill(dist.begin(), dist.end(), std::numeric_limits<T>::max());
        dist[s] = 0, Q.push({0, s});
        while (not Q.empty()) {
            const T cost = Q.top().first;
            const Ind v = Q.top().second;
            Q.pop();
            if (dist[v] < cost) { continue; }
            for (Ind i = 0; i < (Ind)cflow.edge[v].size(); i++) {
                const auto& e = cflow.edge[v][i];
                const T pd = potential[v] - potential[e.to];
                if (e.cap == 0 or dist[e.to] <= dist[v] + (T)e.cost + pd) { continue; }
                dist[e.to] = dist[v] + (T)e.cost + pd, prev_v[e.to] = v, prev_e[e.to] = i;
                Q.push({dist[e.to], e.to});
            }
        }
        if (dist[t] == std::numeric_limits<T>::max()) { return {false, ans}; }
        for (Ind v = 0; v < V; v++) { potential[v] += dist[v]; }
        Cap d = f;
        for (Ind v = t; v != s; v = prev_v[v]) {
            const auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            d = std::min(d, e.cap);
        }
        f = (Cap)(f - d), ans += (T)d * potential[t];
        for (Ind v = t; v != s; v = prev_v[v]) {
            auto& e = cflow.edge[prev_v[v]][prev_e[v]];
            e.cap = (Cap)(e.cap - d), cflow.edge[v][e.rev].cap = (Cap)(cflow.edge[v][e.rev].cap + d);
        }
    }
    return {true, ans};
}
//!============================================!//
//!    8888ba.88ba             oo              !//
//!    88  '8b  '8b                            !//
//!    88   88   88  .d8888b.  dP  88d888b.    !//
//!    88   88   88  88'  '88  88  88'  '88    !//
//!    88   88   88  88.  .88  88  88    88    !//
//!    dP   dP   dP  '88888P8  dP  dP    dP    !//
//!============================================!//
int main()
{
    const int N = read<int>();
    const int V = 2 * N + 6;
    const int S = V - 2, T = V - 1, D = 2 * N;
    constexpr ll BASE = 2000000000LL;
    CostFlow<int, ll, int> CF(V);
    int F = 0;
    for (int i = 0; i < N; i++) {
        ll rx, ry;
        int rc;
        std::cin >> rx >> ry >> rc, F += rc;
        CF.addEdge(S, i, rc, 0);
        CF.addEdge(i, D + 0, INF<int>, +rx + ry + BASE);
        CF.addEdge(i, D + 1, INF<int>, +rx - ry + BASE);
        CF.addEdge(i, D + 2, INF<int>, -rx + ry + BASE);
        CF.addEdge(i, D + 3, INF<int>, -rx - ry + BASE);
    }
    for (int i = 0; i < N; i++) {
        ll bx, by;
        int bc;
        std::cin >> bx >> by >> bc;
        CF.addEdge(N + i, T, bc, 0);
        CF.addEdge(D + 0, N + i, INF<int>, -bx - by + BASE);
        CF.addEdge(D + 1, N + i, INF<int>, -bx + by + BASE);
        CF.addEdge(D + 2, N + i, INF<int>, +bx - by + BASE);
        CF.addEdge(D + 3, N + i, INF<int>, +bx + by + BASE);
    }
    std::cout << -PrimalDual<ll>(CF, S, T, F).second + F * BASE * 2LL << std::endl;
    return 0;
}


Measured memory_bytes: 1408