#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <limits>
#include <numeric>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#pragma comment(linker, "/STACK:36777216")

using namespace std;

#define MP make_pair
#define all(v) (v).begin(), (v).end()
#define PROBLEM_ID "A"

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<bool> vb;
typedef long double ld;
typedef pair<int, int> pii;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<vvl> vvvl;
typedef pair<ll, ll> pll;

ll ManhattanMaxMatchingStupid(const vvi& red, const vvi& blue) {
  vector<pii> red_points, blue_points;
  for (int i = 0; i < red.size(); ++i) {
    for (int j = 0; j < red[i][2]; ++j) {
      red_points.push_back(MP(red[i][0], red[i][1]));
    }
  }
  for (int i = 0; i < blue.size(); ++i) {
    for (int j = 0; j < blue[i][2]; ++j) {
      blue_points.push_back(MP(blue[i][0], blue[i][1]));
    }
  }
  int n = red_points.size();
  vi perm;
  for (int i = 0; i < n; ++i) {
    perm.push_back(i);
  }
  ll res = 0;
  do {
    ll curres = 0;
    for (int i = 0; i < n; ++i) {
      curres += abs(blue_points[perm[i]].first - red_points[i].first) + abs(blue_points[perm[i]].second - red_points[i].second);
    }
    if (curres > res) {
      res = curres;
    }
  } while (next_permutation(perm.begin(), perm.end()));
  return res;
}

// min cost max flow adjacency lists maxflow dijkstra with potentials dejkstra deykstra
const int INT_INF = 1000000000;
const ll INF = ll(INT_INF) * ll(INT_INF);
int N, s, t;

struct Edge {
  int from;
  int to;
  int cap;
  ll cost;
  int rev;

  Edge(int from_, int to_, int cap_, ll cost_, int rev_) : from(from_), to(to_), cap(cap_), cost(cost_), rev(rev_) {}
};

vector<Edge> edges;
vvi outgoing;

void AddEdge(int from, int to, int cap, ll cost) {
  Edge direct(from, to, cap, cost, edges.size() + 1);
  Edge back(to, from, 0, -cost, edges.size());
  outgoing[from].push_back(edges.size());
  edges.push_back(direct);
  outgoing[to].push_back(edges.size());
  edges.push_back(back);
}

pair<int, ll> minCostMaxFlow() {
  int result = 0;
  ll flow_cost = 0;
  vector<ll> dist(N, INF);
  dist[s] = 0;
  vector<int> last_edge(N, -1);
  for (int step = 0; step < N; ++step) {
    bool changed = false;
    for (int i = 0; i < edges.size(); ++i) {
      int from = edges[i].from;
      int to = edges[i].to;
      if (edges[i].cap > 0 && dist[to] > dist[from] + edges[i].cost) {
        dist[to] = dist[from] + edges[i].cost;
        last_edge[to] = i;
        changed = true;
      }
    }
    if (!changed) {
      break;
    }
  }
  vector<ll> p = dist;
  while (true) {
    if (last_edge[t] == -1) {
      break;
    }
    int min_flow = INT_INF;
    int last = t;
    while (true) {
      int pr_edge = last_edge[last];
      if (pr_edge != -1) {
        min_flow = min(min_flow, edges[pr_edge].cap);
      }
      else {
        break;
      }
      last = edges[pr_edge].from;
    }
    if (min_flow == 0) {
      break;
    }
    result += min_flow;
    last = t;
    while (true) {
      int pr_edge = last_edge[last];
      if (pr_edge != -1) {
        edges[pr_edge].cap -= min_flow;
        edges[edges[pr_edge].rev].cap += min_flow;
        flow_cost += min_flow * edges[pr_edge].cost;
      }
      else {
        break;
      }
      last = edges[pr_edge].from;
    }
    dist.assign(N, INF);
    last_edge.assign(N, -1);
    vector<bool> done(N, false);
    dist[s] = 0;
    set<pair<ll, int> > q;
    for (int i = 0; i < N; ++i) {
      q.insert(MP(dist[i], i));
    }
    for (int i = 0; i < N; ++i) {
      pair<ll, int> closest = *q.begin();
      q.erase(closest);
      ll cur_dist = closest.first;
      int min_index = closest.second;
      done[min_index] = true;
      for (int j = 0; j < outgoing[min_index].size(); ++j) {
        int edge_index = outgoing[min_index][j];
        int to = edges[edge_index].to;
        if (!done[to] && edges[edge_index].cap > 0 && dist[to] > dist[min_index] + edges[edge_index].cost + p[min_index] - p[to]) {
          q.erase(MP(dist[to], to));
          dist[to] = dist[min_index] + edges[edge_index].cost + p[min_index] - p[to];
          q.insert(MP(dist[to], to));
          last_edge[to] = edge_index;
        }
      }
    }
    for (int i = 0; i < N; ++i) {
      p[i] += dist[i];
    }
  }
  return MP(result, flow_cost);
}


ll ManhattanMaxMatching(const vvi& red, const vvi& blue) {
  int n = red.size();
  vi xs, ys;
  for (int i = 0; i < red.size(); ++i) {
    for (int j = 0; j < red[i][2]; ++j) {
      xs.push_back(red[i][0]);
      ys.push_back(red[i][1]);
    }
  }
  for (int i = 0; i < blue.size(); ++i) {
    for (int j = 0; j < blue[i][2]; ++j) {
      xs.push_back(blue[i][0]);
      ys.push_back(blue[i][1]);
    }
  }
  sort(xs.begin(), xs.end());
  int xmid = xs[xs.size() / 2];
  sort(ys.begin(), ys.end());
  int ymid = ys[ys.size() / 2];
  ll res = 0;
  for (int i = 0; i < red.size(); ++i) {
    res += red[i][2] * (ll(abs(red[i][0] - xmid)) + ll(abs(red[i][1] - ymid)));
  }
  for (int i = 0; i < blue.size(); ++i) {
    res += blue[i][2] * (ll(abs(blue[i][0] - xmid)) + ll(abs(blue[i][1] - ymid)));
  }
  N = 2 * n + 6;
  s = N - 1;
  t = N - 2;
  outgoing.clear();
  outgoing.resize(N);
  for (int i = 0; i < red.size(); ++i) {
    int x = red[i][0] <= xmid ? 0 : 1;
    int y = red[i][1] <= ymid ? 0 : 1;
    AddEdge(s, i, red[i][2], 0);
    for (int j = 0; j < 4; ++j) {
      ll cost = 0;
      cost += abs(x - (j & 1)) * ll(2) * abs(xmid - red[i][0]);
      cost += abs(y - ((j >> 1) & 1)) * ll(2) * abs(ymid - red[i][1]);
      AddEdge(i, 2 * n + j, INT_INF, cost);
    }    
  }
  for (int i = 0; i < blue.size(); ++i) {
    int x = blue[i][0] > xmid ? 0 : 1;
    int y = blue[i][1] > ymid ? 0 : 1;
    AddEdge(n + i, t, blue[i][2], 0);
    for (int j = 0; j < 4; ++j) {
      ll cost = 0;
      cost += abs(x - (j & 1)) * ll(2) * abs(xmid - blue[i][0]);
      cost += abs(y - ((j >> 1) & 1)) * ll(2) * abs(ymid - blue[i][1]);
      AddEdge(2 * n + j, n + i, INT_INF, cost);
    }
  }
  pair<int, ll> min_cost_max_flow = minCostMaxFlow();
  return res - min_cost_max_flow.second;
}

int main() {
  int n;
  cin >> n;
  vvi red(n, vi(3)), blue(n, vi(3));
  for (int i = 0; i < n; ++i) {
    scanf("%d%d%d", &red[i][0], &red[i][1], &red[i][2]);
  }
  for (int i = 0; i < n; ++i) {
    scanf("%d%d%d", &blue[i][0], &blue[i][1], &blue[i][2]);
  }
  ll res = ManhattanMaxMatching(red, blue);
  cout << res << endl;
  return 0;
}


Measured memory_bytes: 1784