#include <bits/stdc++.h>

#define MIN_INT -2147483648
#define MAX_INT 2147483647
#define MIN_LONG -9223372036854775808L
#define MAX_LONG 9223372036854775807L

#define long long long int

using namespace std;

// @author: pashka


struct edge {
    int src, dst, cap, cost, flw;
};

vector<edge> edges;
vector<vector<int>> graph;

void dijkstra(int s, vector<long> &phi, vector<long> &d, vector<int> &prev) {
    std::fill(d.begin(), d.end(), MAX_LONG);
    d[s] = 0;
    std::priority_queue<pair<long, int>> pq;
    pq.push({-d[s], s});
    while (!pq.empty()) {
        int v = pq.top().second;
        long cur_d = -pq.top().first;
        pq.pop();
        if (cur_d > d[v]) continue;
        for (int j = 0; j < graph[v].size(); ++j) {
            edge &e = edges[graph[v][j]];
            if (e.flw == e.cap) continue;
            long dd = d[v] + e.cost + phi[e.src] - phi[e.dst];
            if (dd < d[e.dst]) {
                d[e.dst] = dd;
                prev[e.dst] = graph[v][j];
                pq.push({-d[e.dst], e.dst});
            }
        }
    }
}

// Returns pair (flow, cost).
pair<int, long> minCostMaxFlow(int s, int t) {
    int n = graph.size();
    int m = edges.size();
    vector<long> phi(n);
    for (int i = 0; i < n; i++) {
        phi[i] = MAX_LONG;
    }
    phi[s] = 0;
    bool ok = false;
    while (!ok) {
        ok = true;
        for (edge &e : edges) {
            if (e.flw < e.cap) {
                int x = e.src;
                int y = e.dst;
                if (phi[x] < MAX_LONG) {
                    if (phi[y] > phi[x] + e.cost) {
                        phi[y] = phi[x] + e.cost;
                        ok = false;
                    }
                }
            }
        }
    }
    int flow = 0;
    long cost = 0;
    vector<long> dist(n);
    vector<int> prev(n);
    while (true) {
        dijkstra(s, phi, dist, prev);
        if (dist[t] == MAX_LONG) break;
        {
            int i = t;
            int delta = MAX_INT;
            while (i != s) {
                edge &e = edges[prev[i]];
                delta = std::min(delta, e.cap - e.flw);
                i = e.src;
            }
            assert(delta >= 0);
            flow += delta;
            i = t;
            while (i != s) {
                edge &e = edges[prev[i]];
                edge &er = edges[prev[i] ^ 1];
                e.flw += delta;
                er.flw -= delta;
                assert(e.flw <= e.cap);
                cost += (long) e.cost * delta;
                i = e.src;
            }
        }
        for (int i = 0; i < n; i++) {
            phi[i] += dist[i];
        }
    }
    return {flow, cost};
}

void addEdge(int u, int v, int cap, int cost) {
//    cout << u << " " << v << " " << cost << "\n";
    edges.push_back({u, v, cap, cost, 0});
    edges.push_back({v, u, 0, -cost, 0});
    graph[u].push_back(edges.size() - 2);
    graph[v].push_back(edges.size() - 1);
}



int main() {
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    n;
    vector<int> x(2 * n);
    vector<int> y(2 * n);
    vector<int> r(2 * n);

    for (int i = 0; i < 2 * n; i++) {
        cin >> x[i];
        cin >> y[i];
        cin >> r[i];
    }

    graph.resize(2 * n + 6);

    int S = 2 * n;
    int T = 2 * n + 1;
    int A = 2 * n + 2;
    int B = 2 * n + 3;
    int C = 2 * n + 4;
    int D = 2 * n + 5;

    for (int i = 0; i < n; i++) {
        addEdge(S, i, r[i], 0);
        addEdge(i, A, r[i], -x[i] - y[i]);
        addEdge(i, B, r[i], +x[i] - y[i]);
        addEdge(i, C, r[i], -x[i] + y[i]);
        addEdge(i, D, r[i], +x[i] + y[i]);
    }
    for (int i = n; i < 2 * n; i++) {
        addEdge(i, T, r[i], 0);
        addEdge(A, i, r[i], + x[i] + y[i]);
        addEdge(B, i, r[i], - x[i] + y[i]);
        addEdge(C, i, r[i], + x[i] - y[i]);
        addEdge(D, i, r[i], - x[i] - y[i]);
    }

    auto res = minCostMaxFlow(S, T);

    cout << -res.second;

    return 0;
}

Measured memory_bytes: 1172