Problem:
Score : 1200 points

Problem Statement

Snuke is playing with red and blue balls, placing them on a two-dimensional plane.

First, he performed N operations to place red balls. In the i-th of these operations, he placed RC_i red balls at coordinates (RX_i,RY_i).
Then, he performed another N operations to place blue balls. In the i-th of these operations, he placed BC_i blue balls at coordinates (BX_i,BY_i).
The total number of red balls placed and the total number of blue balls placed are equal, that is, \sum_{i=1}^{N} RC_i = \sum_{i=1}^{N} BC_i. Let this value be S.

Snuke will now form S pairs of red and blue balls so that every ball belongs to exactly one pair.
Let us define the score of a pair of a red ball at coordinates (rx, ry) and a blue ball at coordinates (bx, by) as |rx-bx| + |ry-by|.

Snuke wants to maximize the sum of the scores of the pairs.
Help him by finding the maximum possible sum of the scores of the pairs.

Constraints

1 \leq N \leq 1000

0 \leq RX_i,RY_i,BX_i,BY_i \leq 10^9

1 \leq RC_i,BC_i \leq 10

\sum_{i=1}^{N} RC_i = \sum_{i=1}^{N} BC_i

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
RX_1 RY_1 RC_1
RX_2 RY_2 RC_2
\vdots
RX_N RY_N RC_N
BX_1 BY_1 BC_1
BX_2 BY_2 BC_2
\vdots
BX_N BY_N BC_N

Output

Print the maximum possible sum of the scores of the pairs.

Sample Input 1

2
0 0 1
3 2 1
2 2 1
5 0 1

Sample Output 1

8

If we pair the red ball at coordinates (0,0) and the blue ball at coordinates (2,2), the score of this pair is |0-2| + |0-2|=4.
Then, if we pair the red ball at coordinates (3,2) and the blue ball at coordinates (5,0), the score of this pair is |3-5| + |2-0|=4.
Making these two pairs results in the total score of 8, which is the maximum result.

Sample Input 2

3
0 0 1
2 2 1
0 0 2
1 1 1
1 1 1
3 3 2

Sample Output 2

16

Snuke may have performed multiple operations at the same coordinates.

Sample Input 3

10
582463373 690528069 8
621230322 318051944 4
356524296 974059503 6
372751381 111542460 9
392867214 581476334 6
606955458 513028121 5
882201596 791660614 9
250465517 91918758 3
618624774 406956634 6
426294747 736401096 5
974896051 888765942 5
726682138 336960821 3
715144179 82444709 6
599055841 501257806 6
390484433 962747856 4
912334580 219343832 8
570458984 648862300 6
638017635 572157978 10
435958984 585073520 7
445612658 234265014 6

Sample Output 3

45152033546

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

#![allow(non_snake_case, unused)]
use std::collections::*;

////////// missing functions in 1.15.1 //////////
macro_rules! eprint {
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = write!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! eprintln {
	() => { eprintln!(""); };
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = writeln!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! dbg {
	($v:expr) => {{
		let val = $v;
		eprintln!("[{}:{}] {} = {:?}", file!(), line!(), stringify!($v), val);
		val
	}}
}
/////////////////////////////////////////////////
pub trait SetMinMax {
	fn setmin(&mut self, v: Self) -> bool;
	fn setmax(&mut self, v: Self) -> bool;
}
impl<T> SetMinMax for T where T: PartialOrd {
	fn setmin(&mut self, v: T) -> bool {
		*self > v && { *self = v; true }
	}
	fn setmax(&mut self, v: T) -> bool {
		*self < v && { *self = v; true }
	}
}

macro_rules! mat {
	($($e:expr),*) => { Vec::from(vec![$($e),*]) };
	($($e:expr,)*) => { Vec::from(vec![$($e),*]) };
	($e:expr; $d:expr) => { Vec::from(vec![$e; $d]) };
	($e:expr; $d:expr $(; $ds:expr)+) => { Vec::from(vec![mat![$e $(; $ds)*]; $d]) };
}

macro_rules! ok {
	($a:ident$([$i:expr])*.$f:ident()$(@$t:ident)*) => {
		$a$([$i])*.$f($($t),*)
	};
	($a:ident$([$i:expr])*.$f:ident($e:expr$(,$es:expr)*)$(@$t:ident)*) => { {
		let t = $e;
		ok!($a$([$i])*.$f($($es),*)$(@$t)*@t)
	} };
}

pub fn readln() -> String {
	let mut line = String::new();
	::std::io::stdin().read_line(&mut line).unwrap_or_else(|e| panic!("{}", e));
	line
}

macro_rules! read {
	($($t:tt),*; $n:expr) => {{
		let stdin = ::std::io::stdin();
		let ret = ::std::io::BufRead::lines(stdin.lock()).take($n).map(|line| {
			let line = line.unwrap();
			let mut it = line.split_whitespace();
			_read!(it; $($t),*)
		}).collect::<Vec<_>>();
		ret
	}};
	($($t:tt),*) => {{
		let line = readln();
		let mut it = line.split_whitespace();
		_read!(it; $($t),*)
	}};
}

macro_rules! _read {
	($it:ident; [char]) => {
		_read!($it; String).chars().collect::<Vec<_>>()
	};
	($it:ident; [u8]) => {
		Vec::from(_read!($it; String).into_bytes())
	};
	($it:ident; usize1) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1
	};
	($it:ident; [usize1]) => {
		$it.map(|s| s.parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1).collect::<Vec<_>>()
	};
	($it:ident; [$t:ty]) => {
		$it.map(|s| s.parse::<$t>().unwrap_or_else(|e| panic!("{}", e))).collect::<Vec<_>>()
	};
	($it:ident; $t:ty) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<$t>().unwrap_or_else(|e| panic!("{}", e))
	};
	($it:ident; $($t:tt),+) => {
		($(_read!($it; $t)),*)
	};
}

pub fn main() {
	let _ = ::std::thread::Builder::new().name("run".to_string()).stack_size(32 * 1024 * 1024).spawn(run).unwrap().join();
}

fn run() {
	let N = read!(usize);
	let R = read!(i64, i64, i64; N);
	let B = read!(i64, i64, i64; N);
	let mut g = Graph::new(2 * N + 1);
	for i in 0..N {
		g.add(2 * N, i, R[i].2, 0);
		g.add(N + i, 2 * N, B[i].2, 0);
		for j in 0..N {
			g.add(i, N + j, 10, -(R[i].0 - B[j].0).abs() - (R[i].1 - B[j].1).abs());
		}
	}
	g.solve();
	println!("{}", -g.val());
}

#[derive(Copy, Clone, Debug)]
pub struct E {
	pub to: usize,
	pub cap: i64,
	pub init: i64,
	pub cost: i64,
	pub rev: usize
}

#[derive(Clone, Debug)]
pub struct Graph {
	pub es: Vec<Vec<E>>,
	pub ex: Vec<i64>,
	pub p: Vec<i64>,
	iter: Vec<usize>
}

impl Graph {
	pub fn new(n: usize) -> Graph {
		Graph { es: vec![vec![]; n], ex: vec![0; n], p: vec![0; n], iter: vec![0; n] }
	}
	pub fn add(&mut self, v: usize, to: usize, cap: i64, cost: i64) {
		let (fwd, rev) = (self.es[v].len(), self.es[to].len());
		self.es[v].push(E { to: to, cap: cap, init: cap, cost: cost, rev: rev });
		self.es[to].push(E { to: v, cap: 0, init: 0, cost: -cost, rev: fwd });
	}
	fn is_admissible(&self, v: usize, e: &E) -> bool {
		e.cap > 0 && e.cost + self.p[v] - self.p[e.to] < 0
	}
	/// Compute minimum cost circulation.
	/// Return whether there is a flow satisfying the demand constraints.
	/// flow(e) = init(e) - cap(e).
	/// For solving min cost s-t flow of value F, set ex(s)=F and ex(t)=-F.
	/// For every vertex, the total capacity of its incident edges must be fit in i64.
	/// Dual: minimize \sum_v ex(v)p(v) + \sum_{uv} cap(e) max(0, -cost(uv) - p(u) + p(v)).
	/// O(V^2 E log VC), where C=max(cost(e)). When cap=1, O(V E log VC).
	pub fn solve(&mut self) -> bool {
		let n = self.es.len();
		let mut eps = 0;
		for v in &mut self.es {
			for e in v {
				e.cost *= n as i64;
				eps.setmax(e.cost);
			}
		}
		let mut stack = vec![];
		let mut visit = vec![false; n];
		let mut ok = self.ex.iter().all(|&ex| ex == 0);
		'refine: loop {
			eps = std::cmp::max(1, eps / 8);
			if ok && self.fitting() {
				break;
			}
			for v in 0..n {
				for i in 0..self.es[v].len() {
					let e = self.es[v][i];
					if self.is_admissible(v, &e) {
						self.ex[e.to] += e.cap;
						self.ex[v] -= e.cap;
						self.es[e.to][e.rev].cap += e.cap;
						self.es[v][i].cap = 0;
					}
				}
			}
			loop {
				for v in 0..n {
					self.iter[v] = 0;
					if self.ex[v] > 0 {
						visit[v] = true;
						stack.push(v);
					} else {
						visit[v] = false;
					}
				}
				if stack.len() == 0 { break }
				while let Some(v) = stack.pop() {
					for e in &self.es[v] {
						if !visit[e.to] && self.is_admissible(v, e) {
							visit[e.to] = true;
							stack.push(e.to);
						}
					}
				}
				if (0..n).filter(|&v| visit[v]).flat_map(|v| self.es[v].iter()).all(|e| e.cap <= 0 || visit[e.to]) {
					assert!(!ok);
					break 'refine;
				}
				for v in (0..n).filter(|&v| visit[v]) { self.p[v] -= eps }
				for v in 0..n {
					while self.ex[v] > 0 {
						let tmp = self.ex[v];
						let f = self.dfs(v, tmp);
						if f == 0 { break }
						else { self.ex[v] -= f }
					}
				}
			}
			ok = true;
		}
		for v in &mut self.es {
			for e in v {
				e.cost /= n as i64;
			}
		}
		ok
	}
	fn dfs(&mut self, v: usize, f: i64) -> i64 {
		if self.ex[v] < 0 {
			let d = ::std::cmp::min(f, -self.ex[v]);
			self.ex[v] += d;
			return d;
		}
		while self.iter[v] < self.es[v].len() {
			let e = self.es[v][self.iter[v]];
			if self.is_admissible(v, &e) {
				let d = self.dfs(e.to, ::std::cmp::min(f, e.cap));
				if d > 0 {
					self.es[v][self.iter[v]].cap -= d;
					self.es[e.to][e.rev].cap += d;
					return d;
				}
			}
			self.iter[v] += 1;
		}
		0
	}
	fn fitting(&mut self) -> bool {
		let n = self.es.len();
		let mut d: Vec<i64> = self.p.iter().map(|&a| a / (n as i64)).collect(); // p must be non-positive.
		let mut d2: Vec<i64> = (0..n).map(|v| d[v] * (n as i64) - self.p[v] + 1).collect();
		let mut fixed = vec![false; n];
		let mut que = ::std::collections::BinaryHeap::new();
		for v in 0..n {
			que.push((-d2[v], v))
		}
		while let Some((_, v)) = que.pop() {
			if fixed[v] { continue }
			fixed[v] = true;
			for e in &self.es[v] {
				if e.cap > 0 && { let tmp = d2[v] + e.cost + self.p[v] - self.p[e.to] + 1; d2[e.to].setmin(tmp) } {
					if fixed[e.to] {
						return false;
					}
					d[e.to] = d[v] + e.cost / (n as i64);
					que.push((-d2[e.to], e.to));
				}
			}
		}
		self.p = d;
		true
	}
	pub fn val(&self) -> i64 {
		let mut tot = 0;
		for v in &self.es {
			for e in v {
				if e.cap < e.init {
					tot += (e.init - e.cap) * e.cost;
				}
			}
		}
		tot
	}
}