#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <cstring>
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <list>  
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;  

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }

typedef struct MCMF {
	int n,m;
	vector<int> ghead,gnxt,gto,gcap; vector<ll> gcost;

	vector<ll> d; vector<int> bck; vector<ll> pot; vector<int> flow;

	//int ghead[MAXGN],gnxt[2*MAXGM],gto[2*MAXGM],gcap[2*MAXGM],gcost[2*MAXGM];
	//int d[MAXGN]; int bck[MAXGN];
	//int pot[MAXGN];

	void init(int _n) { n=_n,m=0; ghead=vector<int>(n,-1); gnxt.clear(),gto.clear(),gcap.clear(),gcost.clear(); d=vector<ll>(n); bck=vector<int>(n); pot=vector<ll>(n,0); flow=vector<int>(n); }
	void addedge(int a,int b,int c,ll d) {
		gnxt.PB(ghead[a]); ghead[a]=m; gto.PB(b); gcap.PB(c); gcost.PB(+d); ++m;
		gnxt.PB(ghead[b]); ghead[b]=m; gto.PB(a); gcap.PB(0); gcost.PB(-d); ++m;
		//printf("adding edge %d-%d with cap %d and cost %lld\n",a,b,c,d);
	}
	pair<int,ll> solve(int s,int t) {
		//REP(i,n) { printf("%d:",i); for(int x=ghead[i];x!=-1;x=gnxt[x]) printf(" %d",gto[x]); puts(""); }

		REP(i,n) d[i]=LLONG_MAX,bck[i]=-1; d[s]=0,bck[s]=-2;
		while(true) {
			bool change=false;
			REP(at,n) if(d[at]!=LLONG_MAX) for(int x=ghead[at];x!=-1;x=gnxt[x]) if(gcap[x]>0) {
				int to=gto[x]; if(d[at]+gcost[x]>=d[to]) continue;
				d[to]=d[at]+gcost[x]; bck[to]=x^1; change=true;
			}
			if(!change) break;
		}
		if(d[t]==LLONG_MAX) return MP(0,0);
		REP(i,n) pot[i]=d[i];


		pair<int,ll> ret=MP(0,0LL);
		while(true) {
			REP(i,n) d[i]=LLONG_MAX,bck[i]=-1,flow[i]=0; d[s]=0,bck[s]=-2,flow[s]=INT_MAX;
			priority_queue<pair<ll,int> > q; q.push(MP(-d[s],s));
			while(!q.empty()) {
				ll cost=-q.top().first; int at=q.top().second; q.pop();
				if(cost>d[at]) continue;
				for(int x=ghead[at];x!=-1;x=gnxt[x]) if(gcap[x]>0) {
					int to=gto[x]; ll rcost=gcost[x]-pot[at]+pot[to]; if(d[at]+rcost>=d[to]) continue;
					d[to]=d[at]+rcost; bck[to]=x^1; flow[to]=min(flow[at],gcap[x]); q.push(MP(-d[to],to));
				}
			}
			if(d[t]==LLONG_MAX) break;
			assert(flow[t]>0);
			//printf("%d\n",d[t]-pot[t]);
			ret.first+=flow[t],ret.second+=(d[t]-pot[t])*flow[t];
			REP(i,n) if(d[i]!=LLONG_MAX) pot[i]-=d[i];

			for(int at=t;at!=s;at=gto[bck[at]]) {
				//printf("%d ",at);
				gcap[bck[at]]+=flow[t]; gcap[bck[at]^1]-=flow[t];
			}
			//printf("%d ",s);
			//puts("");
		}
		return ret;
	}
} MCMF;

const int MAXN=1000;
struct P { int x,y,cnt; };


int n;
P a[MAXN],b[MAXN];

MCMF g;
int sid,tid,aid[MAXN],bid[MAXN],cid[4],nid;

ll solve() {
	nid=0;
	sid=nid++,tid=nid++; REP(i,4) cid[i]=nid++; REP(i,n) aid[i]=nid++; REP(i,n) bid[i]=nid++;
	g.init(nid);
	REP(i,n) g.addedge(sid,aid[i],a[i].cnt,0);
	REP(i,n) REP(mask,4) g.addedge(aid[i],cid[mask],a[i].cnt,-(((mask&1)?+a[i].x:-a[i].x)+((mask&2)?+a[i].y:-a[i].y)));
	REP(i,n) REP(mask,4) g.addedge(cid[mask],bid[i],b[i].cnt,-(((mask&1)?-b[i].x:+b[i].x)+((mask&2)?-b[i].y:+b[i].y)));
	REP(i,n) g.addedge(bid[i],tid,b[i].cnt,0);
	pair<int,ll> res=g.solve(sid,tid);
	return -res.second;
}

void run() {
	scanf("%d",&n);
	REP(i,n) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].cnt);
	REP(i,n) scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].cnt);
	printf("%lld\n",solve());
}

int main() {
	run();
	return 0;
}


Measured memory_bytes: 1152