#include <iostream>
#include <numeric>
#include <vector>
#include <limits>

using lint = long long;

template <class Cap, class Cost, bool isDirect>
class MinCostFlow {
    struct Edge {
        int src, dst;
        Cap cap;
        Cost cost;
        int rev;
        Edge(int src, int dst, Cap cap, Cost cost, int rev)
            : src(src), dst(dst), cap(cap), cost(cost), rev(rev){};
    };

    class Graph {
    public:
        int size;
        std::vector<std::vector<Edge>> path;

        explicit Graph(int N = 0) : size(N), path(size) {}
        void span(int src, int dst, Cap cap, Cost cost, int rev) {
            path[src].push_back(Edge(src, dst, cap, cost, rev));
        }
        std::vector<Edge>& operator[](int v) { return path[v]; }
    };

public:
    const Cost INF = std::numeric_limits<Cost>::max();
    Graph graph;
    std::vector<Cost> dist;
    std::vector<Edge*> rev;

    explicit MinCostFlow(int N) : graph(N), dist(N), rev(N) {}

    void span(int src, int dst, Cap cap, Cost cost) {
        graph.span(src, dst, cap, cost, graph[dst].size());
        graph.span(dst, src, (isDirect ? 0 : cap), -cost, graph[src].size() - 1);
    }

    void BellmanFord(int s) {
        fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;

        bool update = true;
        while (update) {
            update = false;
            for (int v = 0; v < graph.size; ++v) {
                if (dist[v] == INF) continue;
                for (auto& e : graph[v]) {
                    if (e.cap > 0 && dist[e.dst] > dist[e.src] + e.cost) {
                        dist[e.dst] = dist[e.src] + e.cost;
                        rev[e.dst] = &e;
                        update = true;
                    }
                }
            }
        }
    }

    Cost exec(int s, int g, Cap flow) {
        Cost ret = 0;

        while (flow > 0) {
            BellmanFord(s);
            if (dist[g] == INF) break;

            Cap f = flow;
            int v = g;
            while (v != s) {
                f = std::min(f, rev[v]->cap);
                v = rev[v]->src;
            }
            flow -= f;
            ret += f * dist[g];

            v = g;
            while (v != s) {
                // rev[v]->dst = v
                rev[v]->cap -= f;
                graph[v][rev[v]->rev].cap += f;
                v = rev[v]->src;
            }
        }
        return (flow > 0 ? -1 : ret);
    }
};

using namespace std;

const int xsgn[4] = {1, 1, -1, -1},
          ysgn[4] = {1, -1, 1, -1};

int main() {
    int N;
    cin >> N;
    vector<lint> rx(N), ry(N), rc(N);
    for (int i = 0; i < N; ++i) {
        cin >> rx[i] >> ry[i] >> rc[i];
    }
    vector<lint> bx(N), by(N), bc(N);
    for (int i = 0; i < N; ++i) {
        cin >> bx[i] >> by[i] >> bc[i];
    }

    MinCostFlow<lint, lint, true> mcf(N * 2 + 4 + 2);
    int s = N * 2 + 4, g = N * 2 + 5;
    vector<int> t(4);
    iota(t.begin(), t.end(), N * 2);

    for (int v = 0; v < N; ++v) {
        mcf.span(s, v, rc[v], 0);
        mcf.span(v + N, g, bc[v], 0);

        for (int i = 0; i < 4; ++i) {
            mcf.span(v, t[i], rc[v], xsgn[i] * rx[v] + ysgn[i] * ry[v]);
            mcf.span(t[i], v + N, bc[v], -xsgn[i] * bx[v] - ysgn[i] * by[v]);
        }
    }

    cout << -mcf.exec(s, g, accumulate(rc.begin(), rc.end(), 0)) << endl;
    return 0;
}


Measured memory_bytes: 1280