# Original solution
N = int(eval(input()))

A = [tuple(map(int,input().split())) for _ in range(N)]

#準備：S_の外延表記sを求める
def settify(S):
  s = []
  i = 0
  while S > 0:
    if (S & 1):  
      s.append(i)
    S = S >> 1
    i += 1
  return s

Sets = []
for S_ in range(2**N):#MLEの可能性あり
  Sets.append(settify(S_))
  
#前処理：集合に対して最適な路線を一つ選ぶO(N^2*2^N)
B = [0 for _ in range(2**N)]
for S_ in range(2**N):
  if S_ == 0:
    ans = 0
    continue
  ans = 10 ** 20
  s = Sets[S_]
  for k in s:
    #南北方向の路線の場合
    sm1 = 0
    #東西方向の路線の場合
    sm2 = 0
    for l in s:
      sm1 += abs(A[k][0] - A[l][0]) * A[l][2]
      sm2 += abs(A[k][1] - A[l][1]) * A[l][2]
    ans = min(ans, sm1, sm2)
    #print(S_, s, ans, sm1, sm2) 
  B[S_] = ans
  
#Bit_DP... DP[S][i] = min{DP[S-T][i-1]+B[T]| T<S} 
DP = [[0 for _ in range(N+2)] for _ in range(2**N)] #0番目を南北、1番目を東西大通りとする

#南北大通りO(N*2^N)
for S_ in range(2**N):
  #S = S_
  #i = 0
  for i in Sets[S_]:
  #while S > 0:
    #if (S & 1): 
      #print(i,S_,S,DP)
    DP[S_][0] += abs(A[i][0])*A[i][2]
    #S = S >> 1
    #i += 1
  #print(S_, DP[S_][0])

#東西大通りの下準備O(N*2^N)
C = [0 for _ in range(2**N)]
for S_ in range(2**N):
  """
  S = S_
  i = 0
  while S > 0:
    if (S & 1): 
  """
  for i in Sets[S_]:
    C[S_] += abs(A[i][1])*A[i][2]
    #S = S >> 1
    #i += 1
  
#東西大通り
for S_ in range(2**N):
  if S_ == 0:
    continue
  s = Sets[S_]
  DP[S_][1] = 10**20 
  #Sの部分集合を列挙して、DP[*][1]を実行
  for T_ in range(2**len(s)):
    #T = T_
    #i = 0
    L = 0
    """
    while T > 0:
      if (T & 1):
    """
    for i in Sets[T_]:
      L += 2**s[i]
      #T = T >> 1
      #i += 1
    DP[S_][1] = min(DP[S_][1], DP[S_-L][0] + C[L])

#DP[*][2~]を実行
for k in range(N): #DP[*][k+2]
  for S_ in range(2**N):
    if S_ == 0: continue
    #S = S_
    s = Sets[S_] 
    #S = S_
    DP[S_][k+2] = 10**20 
    #Sの部分集合を列挙して、DP[*][k+2]を実行
    for T_ in range(2**len(s)):
      #T = T_
      #i = 0
      L = 0
      """
      while T > 0:
        if (T & 1):
      """
      for i in Sets[T_]:
        L += 2**s[i]
        #T = T >> 1
        #i += 1
      DP[S_][k+2] = min(DP[S_][k+2], DP[S_-L][k+1] + B[L])
#print(B,C)   
#print(DP)
for k in range(-1,N):
  print((DP[2**N-1][k+2]))
 

# Optimized solution
N = int(eval(input()))

A = [tuple(map(int,input().split())) for _ in range(N)]

#準備：S_の外延表記sを求める
def settify(S):
  s = []
  i = 0
  while S > 0:
    if (S & 1):  
      s.append(i)
    S = S >> 1
    i += 1
  return s

Sets = [settify(S_) for S_ in range(2**N)]
b = [2 ** i for i in range(N)] #2べき

def DP_solve(S, A, l, L): #l=0:x, l=1:y, L:最大本数
  if S == 0:
    return [0 for _ in range(L+1)]
  s = Sets[S]
  n = len(s)
  B = [(A[i][l],A[i][2]) for i in s]#位置,コスト(人口)
  B.sort()
  Q = [[0 for _ in range(n)] for _ in range(n)]#準備用
  for j in range(n):
    for k in range(j):#k < j
      Q[k][j] = sum([min(abs(B[l][0]),abs(B[l][0]-B[k][0]),abs(B[l][0]-B[j][0]))*B[l][1] for l in range(k+1,j)])
  DP = [[-1 for _ in range(n)] for _ in range(L+1)]
  #print(DP)
  for j in range(n):
    DP[1][j] = sum([min(abs(B[l][0]),abs(B[l][0]-B[j][0]))*B[l][1] for l in range(j)]) #i本目を置いて、最後がj番目の集落
  for i in range(2,L+1):
    DP[i][0] = DP[i-1][0]
    for j in range(1,n):
      DP[i][j] = min([DP[i-1][k]+Q[k][j] for k in range(j)])
      #i本目を置いて、最後がj番目の集落
      
  return [min([DP[i][j]+sum([min(abs(B[l][0]),abs(B[l][0]-B[j][0]))*B[l][1] for l in range(j+1,n)]) for j in range(n)]) if i >= 1 else sum([abs(B[l][0])*B[l][1] for l in range(n)]) for i in range(L+1)]

#1次元へ帰着
X = [DP_solve(S_,A,0, N) for S_ in range(2**N)]
Y = [DP_solve(S_,A,1, N) for S_ in range(2**N)]
#print(X)  
for k in range(N+1):#合計k本(大通り以外)
  ans = 10**20
  for S_ in range(2**N):#X側に集合S_が割り当てられる
    for i in range(k+1):#x軸平行にi本   
      #print(ans, X[S_][i] + Y[2**N-1-S_][k-i])
      ans = min(ans, X[S_][i] + Y[2**N-1-S_][k-i])
  print(ans)