// Slower C++ solution:
#include <bits/stdc++.h>

//#define fastIO cin.tie(0);ios_base::sync_with_stdio(false)

#define N 10010

#define ll long long

#define INF 1000000000000000000

//min-cost flow problem

using namespace std;



struct edge {

  ll from, to, cap, flow, cost;

};



ll n, d[2 * N + 5], pre[2 * N + 5], Maxflow = 0, COST = 0;

bool inqueue[2 * N + 5];

vector<edge> Edge;     // store edges

vector<ll> G[2 * N + 10];



inline void addEdge( ll from, ll to, ll cap, ll cost )

{

    Edge.push_back( edge{from, to, cap, 0, cost} );

    Edge.push_back( edge{to, from, 0, 0, -cost} );



    G[from].push_back( Edge.size() - 2 );

    G[to].push_back( Edge.size() - 1 );

}



inline bool bfs( ll s, ll t )

{

    for ( int i = 0; i < 2 * N + 5; ++i )

        d[i] = INF;

    memset( inqueue, 0, sizeof( inqueue ) );



    queue<ll> q;

    q.push( s );



    d[s] = 0, inqueue[s] = true;



    ll now;

    while ( q.empty() == false ) {

        now = q.front();

        q.pop();

        inqueue[now]=false;

        for ( ll i = 0; i < G[now].size(); ++i ) {

            edge& tmp = Edge[G[now][i]];

            if ( tmp.cap > tmp.flow && d[now] + tmp.cost < d[tmp.to] ) {

                d[tmp.to] = d[now] + tmp.cost;

                pre[tmp.to] = G[now][i];



                if ( inqueue[tmp.to] == false ) {  //&& tmp.to!=t  not sure

                    inqueue[tmp.to] = true;

                    q.push( tmp.to );

                }

            }

        }

    }



    return d[t] != INF;

    /*

    if(d[t]==-INF)

        return false;

    else

        return true;

    */

}



inline void calc( ll s, ll t )

{

    ll minflow = INF;

    ll tmpu = t;

    while ( s != tmpu ) { //find minflow

        minflow = min( minflow, Edge[pre[tmpu]].cap - Edge[pre[tmpu]].flow );

        tmpu = Edge[pre[tmpu]].from;

    }



    Maxflow += minflow;

    COST += minflow * d[t];



    while ( s != t ) {

        Edge[pre[t]].flow += minflow;

        Edge[pre[t] ^ 1].flow -= minflow;

        t = Edge[pre[t]].from;

    }

}



inline void init()

{

    cin >> n;



    ll a, b, c;

    for ( int i = 1; i <= n; ++i ) {

        cin >> a >> b >> c;

        addEdge( 0, i, c, 0 );

        addEdge( i, 2 * n + 1, c, -a - b );

        addEdge( i, 2 * n + 2, c, a - b );

        addEdge( i, 2 * n + 3, c, -a + b );

        addEdge( i, 2 * n + 4, c, a + b );

    }

    for ( int i = 1; i <= n; ++i ) {

        cin >> a >> b >> c;

        addEdge( i + n, 2 * n + 5, c, 0 );

        addEdge( 2 * n + 1, i + n, c, a + b );

        addEdge( 2 * n + 2, i + n, c, -a + b );

        addEdge( 2 * n + 3, i + n, c, a - b );

        addEdge( 2 * n + 4, i + n, c, -a - b );

    }

}



inline void solve()

{

    ll s = 0, t = 2 * n + 5;



    while ( bfs( s, t ) == true ) {

        calc( s, t );  //update cost && Maxflow

    }

    cout << -COST << endl;

}



int main()

{

    init();

    solve();

}

// Faster C++ solution for the same problem (measured speedup: 1.7468661175011782x):
#include<bits/stdc++.h>

using namespace std;

const int MAXQ = 1e7 + 5;

const int MAXN = 1e3 + 5;

const int MAXP = 5e3 + 5;

const int INF = 1e9;

const long long INFLL = 1e18;

typedef long long ll;

typedef long double ld;

typedef unsigned long long ull;

template <typename T> void chkmax(T &x, T y) {x = max(x, y); }

template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 

template <typename T> void read(T &x) {

	x = 0; int f = 1;

	char c = getchar();

	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;

	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';

	x *= f;

}

template <typename T> void write(T x) {

	if (x < 0) x = -x, putchar('-');

	if (x > 9) write(x / 10);

	putchar(x % 10 + '0');

}

template <typename T> void writeln(T x) {

	write(x);

	puts("");

}

struct edge {int dest, flow, pos, cost; };

vector <edge> a[MAXP];

int s, t, tot, flow; ll cost;

ll dist[MAXP]; int path[MAXP], home[MAXP];

void FlowPath() {

	int p = t, ans = INF;

	while (p != s) {

		ans = min(ans, a[path[p]][home[p]].flow);

		p = path[p];

	}

	flow += ans;

	cost += ans * dist[t];

	p = t;

	while (p != s) {

		a[path[p]][home[p]].flow -= ans;

		a[p][a[path[p]][home[p]].pos].flow += ans;

		p = path[p];

	}

}

bool spfa() {

	static int q[MAXQ];

	static bool inq[MAXP];

	static int l = 0, r = 0;

	for (int i = 0; i <= r; i++)

		dist[q[i]] = INFLL;

	q[l = r = 0] = s, dist[s] = 0, inq[s] = true;

	while (l <= r) {

		int tmp = q[l];

		for (unsigned i = 0; i < a[tmp].size(); i++)

			if (a[tmp][i].flow != 0 && dist[tmp] + a[tmp][i].cost < dist[a[tmp][i].dest]) {

				dist[a[tmp][i].dest] = dist[tmp] + a[tmp][i].cost;

				path[a[tmp][i].dest] = tmp;

				home[a[tmp][i].dest] = i;

				if (!inq[a[tmp][i].dest]) {

					q[++r] = a[tmp][i].dest;

					inq[q[r]] = true;

				}

			}

		l++, inq[tmp] = false;

	}

	return dist[t] != INFLL;

}

void addedge(int x, int y, int z, int c) {

	a[x].push_back((edge){y, z, a[y].size(), c});

	a[y].push_back((edge){x, 0, a[x].size() - 1, -c});

}

int n, mid[4], cntx[MAXN], cnty[MAXN];

pair <int, int> posx[MAXN], posy[MAXN];

int main() {

	read(n), tot = 2 * n;

	s = ++tot, t = ++tot;

	for (int i = 0; i <= 3; i++)

		mid[i] = ++tot;

	for (int i = 1; i <= n; i++) {

		read(posx[i].first), read(posx[i].second), read(cntx[i]);

		addedge(s, i, cntx[i], 0);

		addedge(i, mid[0], INF, -posx[i].first - posx[i].second);

		addedge(i, mid[1], INF, posx[i].first - posx[i].second);

		addedge(i, mid[2], INF, -posx[i].first + posx[i].second);

		addedge(i, mid[3], INF, posx[i].first + posx[i].second);

	}

	for (int i = 1; i <= n; i++) {

		read(posy[i].first), read(posy[i].second), read(cnty[i]);

		addedge(n + i, t, cnty[i], 0);

		addedge(mid[0], n + i, INF, posy[i].first + posy[i].second);

		addedge(mid[1], n + i, INF, -posy[i].first + posy[i].second);

		addedge(mid[2], n + i, INF, posy[i].first - posy[i].second);

		addedge(mid[3], n + i, INF, -posy[i].first - posy[i].second);

	}

	for (int i = 1; i <= tot; i++)

		dist[i] = INFLL;

	while (spfa()) FlowPath();

	writeln(-cost);

	return 0;

}