//use itertools::Itertools;
use std::cmp;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::io::Read;
use std::usize::MAX;

macro_rules! input {(source = $s:expr, $($r:tt)*) => {let mut iter = $s.split_whitespace();let mut next = || { iter.next().unwrap() };input_inner!{next, $($r)*}};($($r:tt)*) => {let stdin = std::io::stdin();let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));let mut next = move || -> String{bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect()};input_inner!{next, $($r)*}};}
macro_rules! input_inner {($next:expr) => {};($next:expr, ) => {};($next:expr, $var:ident : $t:tt $($r:tt)*) => {let $var = read_value!($next, $t);input_inner!{$next $($r)*}};}
macro_rules! read_value {($next:expr, ( $($t:tt),* )) => {( $(read_value!($next, $t)),* )};($next:expr, [ $t:tt ; $len:expr ]) => {(0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()};($next:expr, chars) => {read_value!($next, String).chars().collect::<Vec<char>>()};($next:expr, usize1) => {read_value!($next, usize) - 1};($next:expr, [ $t:tt ]) => {{let len = read_value!($next, usize);(0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()}};($next:expr, $t:ty) => {$next().parse::<$t>().expect("Parse error")};}

fn solve() {
    input! {
        n: usize,
        shuraku: [(i64,i64,usize);n]
    }

    // -のみ
    let mut only_x_walk = vec![vec![MAX; n]; 1 << n];
    let mut only_x_count = vec![0; 1 << n];

    // |のみ
    let mut only_y_walk = vec![vec![MAX; n]; 1 << n];
    let mut only_y_count = vec![0; 1 << n];

    // 大通りのみ
    for i in 0..n {
        only_x_walk[0][i] = shuraku[i].1.abs() as usize * shuraku[i].2;
        only_y_walk[0][i] = shuraku[i].0.abs() as usize * shuraku[i].2;
    }

    for i in 0..1 << n {
        let mut x_set = HashSet::new();
        let mut x_count = 0;
        let mut y_set = HashSet::new();
        let mut y_count = 0;
        // j = iにおいて有効になっている集落
        for j in 0..n {
            only_x_walk[i][j] = cmp::min(only_x_walk[i][j], only_x_walk[0][j]);
            only_y_walk[i][j] = cmp::min(only_y_walk[i][j], only_y_walk[0][j]);

            if i >> j & 1 == 1 {
                if x_set.get(&shuraku[j].1) == None {
                    x_set.insert(shuraku[j].1);
                    x_count += 1;
                }
                if y_set.get(&shuraku[j].0) == None {
                    y_set.insert(shuraku[j].0);
                    y_count += 1;
                }

                // k = jが有効になったことによる最短距離の更新対象となる集落
                for k in 0..n {
                    only_x_walk[i][k] = cmp::min(
                        only_x_walk[i][k],
                        (shuraku[k].1 - shuraku[j].1).abs() as usize * shuraku[k].2,
                    );
                    only_y_walk[i][k] = cmp::min(
                        only_y_walk[i][k],
                        (shuraku[k].0 - shuraku[j].0).abs() as usize * shuraku[k].2,
                    );
                }
            }
        }

        only_x_count[i] = x_count;
        only_y_count[i] = y_count;
    }

    let mut min_dists = vec![MAX; n + 1];

    let mut three_pow = 3usize.pow(n as u32);

    for i in 0..three_pow {
        let mut x_on = 0;
        let mut y_on = 0;

        let mut san_num = i;
        let mut active_senro = 0;

        // 各集落
        for j in 0..n {
            let k = san_num % 3;

            if k == 1 {
                x_on += 1 << j;
                active_senro += 1;
            }

            if k == 2 {
                y_on += 1 << j;
                active_senro += 1;
            }

            san_num /= 3;
        }

        //let active_senro = only_x_count[x_on] + only_y_count[y_on];

        let mut sum_dist = 0;
        for j in 0..n {
            sum_dist += cmp::min(only_x_walk[x_on][j], only_y_walk[y_on][j]);
        }

        //println!("{} {}", active_senro, sum_dist);

        min_dists[active_senro] = cmp::min(min_dists[active_senro], sum_dist);
    }

    for i in 0..n + 1 {
        println!("{}", min_dists[i]);
    }
}

fn main() {
    let thd = std::thread::Builder::new().stack_size(104_857_600);
    thd.spawn(|| solve()).unwrap().join().unwrap();

    /*
    // 入力を一括で読み込む場合
    let mut buf = String::new();
    std::io::stdin().read_to_string(&mut buf).unwrap();
    let mut input = buf.split_whitespace();

    // inputに対しnext()で読み込んでいく
    let q: usize = input.next().unwrap().parse().unwrap();
    */
}

const LARGE_PRIME: u64 = 1_000_000_007;

// @〜でsnippet


Measured memory_bytes: 10996