#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;
struct mcmfedge {
	long long flow, cap, from, to, cost, revid; 
	//flow, capacity, node edge comes from, node edge goes to, index of reverse edge in edgelist
	mcmfedge(long long flow, long long cap, long long cost, int from, int to, int revid): flow(flow), cap(cap), from(from), to(to), cost(cost), revid(revid) {

	}

	bool operator<(mcmfedge* other) {
		return cost < other->cost;
	}
};

struct mcmf {
	// REQUIRED NAMESPACE: std
	// REQUIRED LIBRARIES: vector, queue, algorithm
	// REQUIRED STRUCTS: mcmfedge
	// Automatically detects negative edges and performs bellman ford if existent
	vector <mcmfedge*> edgelist;
	vector <vector <mcmfedge*> > adj;
	vector <mcmfedge*> par;
	vector <long long> potential; 
	vector <long long> dist;
	priority_queue <pair <long long, mcmfedge*>, vector <pair <long long, mcmfedge*> >, greater <pair <long long, mcmfedge*> > > q;
	vector <bool> inq; //for spfa only
	queue <int> qu; //for spfa only
	int source;
	int sink;
	long long INFI = 3000000000000000000LL;
	bool calledMaxFlow = false;
	bool hasInitialNegativeEdges = false;
	int nodeNumber;
	mcmf(int nodeNumber, int source, int sink) {
		this->source = source;
		this->sink = sink;
		this->nodeNumber = nodeNumber;
		par.resize(nodeNumber);
		adj.resize(nodeNumber);
		potential.resize(nodeNumber);
		inq.resize(nodeNumber);
		dist.resize(nodeNumber);
	} 

	void add_edge(int cap, int cost, int from, int to) {
		if (from >= nodeNumber || to >= nodeNumber)
			cout << "Warning: Edge from " << from << " to " << to << " with capacity" << cap << "is out of bounds." << endl; 
		mcmfedge* v = new mcmfedge(0, cap, cost, from, to, edgelist.size() + 1);
		mcmfedge* v_rev = new mcmfedge(0, 0, -cost, to, from, edgelist.size());
		if (cost < 0)
			hasInitialNegativeEdges = true;
		edgelist.push_back(v);
		edgelist.push_back(v_rev);
		adj[from].push_back(v);
		adj[to].push_back(v_rev);
	}

	bool dij_aug_path() {
		for (int i = 0; i < nodeNumber; i++)
			par[i] = NULL, dist[i] = INFI;
		while (!q.empty())
			q.pop();
		q.push(make_pair(0, new mcmfedge(0, 0, 0, source, source, -1)));
		while (!q.empty()) {
			mcmfedge* curedge = q.top().second;
			int curnode = curedge->to;
			long long curdist = q.top().first;
			q.pop();
			if (dist[curnode] == INFI) {
				par[curnode] = curedge;
				dist[curnode] = curdist;
				for (int i = 0; i < adj[curnode].size(); i++) {
					mcmfedge* cur = adj[curnode][i];
					if (cur->cap - cur->flow > 0) {
						q.push(make_pair(curdist + cur->cost + potential[cur->from] - potential[cur->to], cur));
					}					
				}
			}
		}
		return dist[sink] != INFI;
	}

	bool spfa() {
		for (int i = 0; i < nodeNumber; i++)
			par[i] = NULL, dist[i] = INFI, inq[i] = false;
		while (!qu.empty())
			qu.pop();
		qu.push(source);
		dist[source] = 0;
		while (!qu.empty()) {
			int curnode = qu.front();
			qu.pop();
			inq[curnode] = false;
			for (int i = 0; i < adj[curnode].size(); i++) {
				mcmfedge* cur = adj[curnode][i];
				if (dist[curnode] + cur->cost + potential[cur->from] - potential[cur->to] < dist[cur->to] && cur->cap - cur->flow > 0) {
					dist[cur->to] = dist[curnode] + cur->cost + potential[cur->from] - potential[cur->to];
					par[cur->to] = adj[curnode][i];
					if (!inq[cur->to]) {
						qu.push(cur->to);
						inq[cur->to] = true;
					}
				}
			}
		}
		return dist[sink] != INFI;
	}

	pair <long long, long long> set_potentials_and_augment() {
		int curnode = sink;
		long long augment_flow = INFI;
		while (curnode != source) {
			mcmfedge* curpar = par[curnode];
			augment_flow = min(augment_flow, curpar->cap - curpar->flow);
			curnode = curpar->from;
		}
		curnode = sink;
		while (curnode != source) {
			mcmfedge* curpar = par[curnode];
			curpar->flow += augment_flow;
			edgelist[curpar->revid]->flow -= augment_flow;
			curnode = curpar->from;
		}
		for (int i = 0; i < nodeNumber; i++) {
			potential[i] = min(potential[i] + dist[i], INFI);
		} 
		return make_pair(augment_flow, augment_flow * potential[sink]);
	}

	pair <long long, long long> get_mcmf(bool dospfa = false) { //return maxflow, mincost as pair in that order
		for (int i = 0; i < edgelist.size(); i++)
			edgelist[i]->flow = 0; // Reset max flow algorithm

		long long mincost = 0;
		long long maxflow = 0;
		if (dospfa) {
			while (spfa()) {
				pair <long long, long long> mcmf = set_potentials_and_augment();
				mincost += mcmf.second;
				maxflow += mcmf.first;
			}
			return make_pair(maxflow, mincost);
		}
		else if (hasInitialNegativeEdges) {
			bool hasPath = spfa();
			if (!hasPath)
				return make_pair(0, 0);
			pair <long long, long long> mcmf = set_potentials_and_augment();
			mincost += mcmf.second;
			maxflow += mcmf.first;
		}
		calledMaxFlow = true;
		while (dij_aug_path()) {
			pair <long long, long long> mcmf = set_potentials_and_augment();
			mincost += mcmf.second;
			maxflow += mcmf.first;
		}
		return make_pair(maxflow, mincost);
	}

	// optional: the flow values for all edges (in 'add_edge' order).
    // only available after calling get_mcmf
	vector <long long> get_flow_values() {
		vector <long long> flow_values;
		if (calledMaxFlow) {
			for (int i = 0; i < edgelist.size(); i += 2) { //skipping all reverse parallel edges
				flow_values.push_back(edgelist[i]->flow);
			}
		}
		else {
			cout << "Error: cannot get flow values since get_max_flow has not been called" << endl;
		}
		return flow_values;
	}

	// optional: the cost * flow values for all edges (in 'add_edge' order).
    // only available after calling get_mcmf
	vector <long long> get_costflow_values() {
		vector <long long> flow_values;
		if (calledMaxFlow) {
			for (int i = 0; i < edgelist.size(); i += 2) { //skipping all reverse parallel edges
				flow_values.push_back(edgelist[i]->flow * edgelist[i]->cost);
			}
		}
		else {
			cout << "Error: cannot get flow * cost values since get_max_flow has not been called" << endl;
		}
		return flow_values;
	}

	// optional: all edges (in 'add_edge' order).
	// with 0 flow if get_mcmf not yet called, and the max_flow otherwise
    vector<mcmfedge*> get_edges() {
        vector <mcmfedge*> edges;
        for (int i = 0; i < edgelist.size(); i += 2) { //skipping all reverse parallel edges
			edges.push_back(edgelist[i]);
		}
		return edges;
    }
};
int n;
int INF = 1000000000LL;
int main() {

	cin >> n;
	mcmf* mincostmaxflow = new mcmf(2 * n + 6, 0, 1);
	int type[] = {2, 3, 4, 5};
	for (int i = 0; i < n; i++) {
		int x, y, am;
		cin >> x >> y >> am;
		mincostmaxflow->add_edge(am, 0, 0, i + 6);
		mincostmaxflow->add_edge(INF, x + y, i + 6, type[0]);
		mincostmaxflow->add_edge(INF, x - y, i + 6, type[1]);
		mincostmaxflow->add_edge(INF, -x + y, i + 6, type[2]);
		mincostmaxflow->add_edge(INF, -x - y, i + 6, type[3]);
	}

	for (int i = 0; i < n; i++) {
		int x, y, am;
		cin >> x >> y >> am;
		mincostmaxflow->add_edge(am, 0, i + 6 + n, 1);
		mincostmaxflow->add_edge(INF, x + y, type[3], i + n + 6);
		mincostmaxflow->add_edge(INF, x - y, type[2], i + n + 6);
		mincostmaxflow->add_edge(INF, -x + y, type[1], i + n + 6);
		mincostmaxflow->add_edge(INF, -x - y, type[0], i + n + 6);
	}
	vector <mcmfedge*> get_edges = mincostmaxflow->get_edges();
	pair <long long, long long> mcmf = mincostmaxflow->get_mcmf();
	cout << -mcmf.second << '\n';
}

Measured memory_bytes: 2556