Problem:


ルパン四世

怪盗「ルパン四世」は会津藩士を末裔とする美女「富士峰子」より、会津若松市に会津藩が残した軍資金が眠っていることを聞かされる。ルパンの長年の仲間である「石川越ェ門」の報告によれば、軍資金は千両箱に収められいくつかの蔵に保管されている。蔵に見張りはいないが厳重に施錠されている。しかし、越ェ門は彼が父から伝授された秘伝「鋼鉄斬り」の技を繰り出せば瞬時に蔵を破れるという。

残った問題は千両箱の運搬だ。体力のないルパンと越ェ門は千両箱を一つも持てない。そこで、頼りになる男「無限大介」に運搬を頼んだ。
すべての千両箱を運び出すために、ルパンは以下のような計画を立案した。

まず、ルパンの運転で最初の蔵へ行き、越ェ門と大介を降ろす。

越ェ門が蔵を破る

大介がすべての千両箱を運び出す

その千両箱を持ったままルパンが決めた次の蔵へ向かう

これを繰り返し、最後の蔵まで破り千両箱を運び出す。その間にルパンはヘリコプターを準備し最後の蔵で二人と千両箱を運び上げ脱出する。大介はどんなに重いものも運搬できるが、荷物の重さに応じて移動速度は遅くなる。ルパンは、このことを考慮して蔵を破る順番を決めなければならない。

ルパンに代わって、最初の蔵を破ってから最後の蔵に辿りつくまでの移動時間が最小となるような蔵を破る順番を出力するプログラムを作成してください。ただし、

蔵はすべて鶴ヶ城からまっすぐ北に走る通りに面している。蔵の数は高々 15 個であり、城からの距離は高々 10000 メートル以下である。

千両箱の重さはいずれもひとつ 20 キログラムである。それぞれの蔵に収められている千両箱の個数は 10000 個以下である。

蔵から蔵への移動は、通りに沿って地下に設置されている地下道を使う。

大介は w キログラムの荷物を運ぶのに、分速 2,000／(70 + w) メートルで移動する。

入力データは、それぞれの蔵について蔵の番号（100 以下の整数）と城からの距離（メートル）とその蔵に保管されている千両箱の個数が与えられる。

Input

入力は以下の形式で与えられます。

n
s1 d1 v1
s2 d2 v2
:
sn dn vn

1 行目に蔵の個数 n（n ≤ 15）、続く n 行に第 i の蔵の情報が与えられます。蔵の情報として、蔵の番号 si (1 ≤ si ≤ 100)、城からの距離 di (1 ≤ di ≤ 10000)、 千両箱の数 vi (1 ≤ vi ≤ 10000) が１行に与えられます。

Output

蔵を破る順番を１行に出力してください。蔵の番号を空白で区切ってください。

Sample Input 1

2
1 100 1
2 200 2

Output for the Sample Input 1

1 2

Sample Input 2

3
11 100 1
13 200 20
12 300 3

Output for the Sample Input 2

11 12 13

Sample Input 3

5
13 199 1
51 1000 1
37 350 10
27 300 2
99 200 1000

Output for the Sample Input 3

51 37 27 13 99



Sample input:
2
1 100 1
2 200 2


Sample output:
1 2

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i,e in A[:-1]:
    c += 1
    for j,f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

n = input()
D = {}
W = {}
T = {}
for i in range(n):
  x = map(int, raw_input().split())
  p = x[0]
  D[p] = x[1]/20000.0
  W[p] = x[2]*20
  T[p] = 1e9
d_init(n)

p = sorted(W.items(), key = lambda x: -x[1])[0][0]
T [p] = 0
w = sum(W.values())+70
x = []
while T:
  i = sorted(T.items(), key = lambda x: x[1])[0][0]
  t = T.pop(i)
  w -= W[i]
  for j in T.keys():
    tmp = t + D[(i,j)]*w
    if T[j]>tmp: T[j]=tmp
  x.append(str(i))
print " ".join(x[::-1])

Submission status: Wrong Answer

Solution code:
import copy
def d_init(n):
  c = 0
  A = D.items()[:]
  for i,e in A[:-1]:
    c += 1
    for j,f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

n = input()
D = {}
W = {}
T0 = {}
for i in range(n):
  x = map(int, raw_input().split())
  p = x[0]
  D[p] = x[1]/20000.0
  W[p] = x[2]*20
  T0[p] = 1e9
d_init(n)

minT = 1e9
for p in W.keys():
  T = copy.deepcopy(T0)
  T [p] = 0
  w = sum(W.values())+70
  x = []
  while T:
    i = sorted(T.items(), key = lambda x: x[1])[0][0]
    t = T.pop(i)
    w -= W[i]
    for j in T.keys():
      tmp = t + D[(i,j)]*w
      if T[j]>tmp: T[j]=tmp
    x.append(str(i))
  if minT>tmp:
    minT = tmp
    ans = x[::-1]
print " ".join(ans)

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i,e in A:
    c += 1
    for j,f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e9: return tmp1, tmp2

  x1 = 1e9
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / weight
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = x2 + name[idx]
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e9,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a,b,c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

ans1 = 1e9
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e+70)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route:
  print str(e),

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i,e in A:
    c += 1
    for j,f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e9: return tmp1, tmp2

  x1 = 1e9
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / weight
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = x2 + name[idx]
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e9,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a,b,c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20.0
d_init(n)

ans1 = 1e9
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e+70)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route:
  print str(e),

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e9
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / (weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = x2 + name[idx]
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route:
  print str(e),

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e12
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / (weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = x2 + name[idx]
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route:
  print str(e),

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e12
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / (weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = name[idx] + x2
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route[:-1]:
  print str(e),
print str(route[-1])

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e12
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] / (weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = x2 + name[idx]
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route[:-1]:
  print str(e),
print str(route[-1])

Submission status: Wrong Answer

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e12
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] /2000.0/(weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = name[idx] + x2
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route[:-1]:
  print str(e),
print str(route[-1])

Submission status: Accepted

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      tmp = abs(e-f)
      D[(i, j)] = tmp
      D[(j, i)] = tmp
  return

def solve(idx, visited, weight):
  if visited == (1<<n)-1: return 0, name[idx]
  tmp1, tmp2 = dp[idx][visited]
  if tmp1 != 1e12: return tmp1, tmp2

  x1 = 1e12
  for i in range(n):
    i1 = 1<<i
    if (visited & i1) == 0:
      tmp1, tmp2 = solve(i, visited|i1, weight + W[i])
      tmp1 += D[(i, idx)] /2000.0*(weight+70.0)
      if x1 > tmp1:
        x1 = tmp1
        x2 = tmp2
  x2 = name[idx] + x2
  dp[idx][visited] = [x1, x2]
  return x1, x2

name = {}
D = {}
W = {}
n = input()
dp = [[[1e12,[]] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  name[i] = [a]
  D[i] = b
  W[i] = c*20
d_init(n)

ans1 = 1e12
route = []
for i, e in W.items():
  tmp1, tmp2 = solve(i, 1<<i, e)
  if ans1 > tmp1:
    ans1 = tmp1
    route = tmp2

for e in route[:-1]:
  print str(e),
print str(route[-1])

Submission status: Accepted

Solution code:
def d_init(n):
  c = 0
  A = D.items()[:]
  for i, e in A:
    c += 1
    for j, f in A[c:]:
      a = abs(e-f)
      D[(i, j)] = a
      D[(j, i)] = a
  return

def solve(p, v, w):
  if v == (1<<n)-1: return 0, N[p]
  a, b = dp[p][v]
  if a >= 0: return a, b

  T = 1e10
  for i in range(n):
    i1 = 1<<i
    if (v & i1) == 0:
      a, b = solve(i, v|i1, w + W[i])
      a += D[(i, p)] * w
      if T > a:
        T = a
        R = b
  R = N[p] + R
  dp[p][v] = [T, R]
  return T, R

N = {}
D = {}
W = {}
n = input()
dp = [[[-1, []] for _ in [0]*(1<<n)] for _ in [0]*n]
for i in range(n):
  a, b, c = map(int, raw_input().split())
  N[i] = [a]
  D[i] = b/2000.0
  W[i] = c*20
d_init(n)

minT = 1e10
R = []
for i, e in W.items():
  a, b = solve(i, 1<<i, e+70.0)
  if minT > a:
    minT = a
    R = b

for e in R:
  print str(e),

Submission status: Accepted

Solution code:
def calctime(w,dist):
    time=dist/(2000/(70.0+w))
    return time

n=int(raw_input())
s={}
d={}
v={}
for i in xrange(n):
    S,D,V=map(int,raw_input().split())
    s[i]=S
    d[i]=D
    v[i]=V

dist=[[None]*n for _ in xrange(n)]
for i in xrange(n):
    for j in xrange(n):
        if i==j:
            dist[i][j]=float('inf')
        else:
            dist[i][j]=abs(d[i]-d[j])

w=[float('inf')]*(1<<n)
time=[[float('inf')]*n for _ in xrange(1<<n)]
last=[[0]*n for _ in xrange(1<<n)]
for i in xrange(n):
    time[1<<i][i]=0
    w[1<<i]=v[i]*20

for i in xrange(1,1<<n):
    for j in xrange(n):
        if w[i]==float('inf'):continue
        for k in xrange(n):
            if not i>>k&1:
                nexti=i|(1<<k)
                w[nexti]=w[i]+v[k]*20
                if time[nexti][k]>calctime(w[i],dist[j][k])+time[i][j]:
                    time[nexti][k]=calctime(w[i],dist[j][k])+time[i][j]
                    last[nexti][k]=j

ans=[]
now=(1<<n)-1
last_index=time[now].index(min(time[now]))
ans.append(s[last_index])
while now!=0:
    nx=last[now][last_index]
    ans.append(s[nx])
    now=now^(1<<last_index)
    last_index=nx
del ans[-1]
ans.reverse()
print(' '.join(map(str,ans)))

Submission status: Accepted

Solution code:
def calctime(w,dist):
    time=dist/(2000/(70.0+w))
    return time

n=int(raw_input())
s={}
d={}
v={}
for i in xrange(n):
    S,D,V=map(int,raw_input().split())
    s[i]=S
    d[i]=D
    v[i]=V

dist=[[None]*n for _ in xrange(n)]
for i in xrange(n):
    for j in xrange(n):
        if i==j:
            dist[i][j]=float('inf')
        else:
            dist[i][j]=abs(d[i]-d[j])

w=[float('inf')]*(1<<n)
time=[[float('inf')]*n for _ in xrange(1<<n)]
last=[[0]*n for _ in xrange(1<<n)]
for i in xrange(n):
    time[1<<i][i]=0
    w[1<<i]=v[i]*20

for i in xrange(1,1<<n):
    for j in xrange(n):
        if w[i]==float('inf'):continue
        for k in xrange(n):
            if not i>>k&1:
                nexti=i|(1<<k)
                w[nexti]=w[i]+v[k]*20
                if time[nexti][k]>calctime(w[i],dist[j][k])+time[i][j]:
                    time[nexti][k]=calctime(w[i],dist[j][k])+time[i][j]
                    last[nexti][k]=j

ans=[]
now=(1<<n)-1
last_index=time[now].index(min(time[now]))
while now!=0:
    ans.append(s[last_index])
    nx=last[now][last_index]
    now=now^(1<<last_index)
    last_index=nx
ans.reverse()
print(' '.join(map(str,ans)))

Submission status: Accepted

Solution code:
def calctime(w,dist):
    time=dist/(2000/(70.0+w))
    return time

def solve():
    dist=[[None]*n for _ in xrange(n)]
    for i in xrange(n):
        for j in xrange(n):
            if i==j:
                dist[i][j]=float('inf')
            else:
                dist[i][j]=abs(d[i]-d[j])

    w=[float('inf')]*(1<<n)
    time=[[float('inf')]*n for _ in xrange(1<<n)]
    last=[[0]*n for _ in xrange(1<<n)]
    for i in xrange(n):
        time[1<<i][i]=0
        w[1<<i]=v[i]*20

    for i in xrange(1,1<<n):
        for j in xrange(n):
            if w[i]==float('inf'):continue
            for k in xrange(n):
                if not i>>k&1:
                    nexti=i|(1<<k)
                    w[nexti]=w[i]+v[k]*20
                    if time[nexti][k]>calctime(w[i],dist[j][k])+time[i][j]:
                        time[nexti][k]=calctime(w[i],dist[j][k])+time[i][j]
                        last[nexti][k]=j

    ans=[]
    now=(1<<n)-1
    last_index=time[now].index(min(time[now]))
    while now!=0:
        ans.append(s[last_index])
        nx=last[now][last_index]
        now=now^(1<<last_index)
        last_index=nx
    ans.reverse()
    return ans

n=int(raw_input())
s={}
d={}
v={}
for i in xrange(n):
    S,D,V=map(int,raw_input().split())
    s[i]=S
    d[i]=D
    v[i]=V

ans=solve()
print(' '.join(map(str,ans)))

Submission status: Accepted

Solution code:
n = int(input())
D = [list(map(int, input().split())) for i in range(n)]
# [cost, order]
memo = {(2**n-1, i): (0, ()) for i in range(n)}
def dfs(state, pos, w):
    if (state, pos) in memo:
        return memo[state, pos]
    res = None
    for i in range(n):
        if (state >> i) & 1 == 0:
            d0 = D[pos][1]
            s, d1, v = D[i]
            r = dfs(state | (1 << i), i, w + 20*v)
            val = (r[0]+abs(d0-d1)*(70+w), r[1]+(s,))
            if res is None or val < res:
                res = val
    if res:
        memo[state, pos] = res
    return res
def solve():
    for i in range(n):
        s0, d0, v0 = D[i]
        result = dfs(1 << i, i, 20*v0)
        yield result[0], result[1]+(s0,)
ans = min(solve())
print(*reversed(ans[1]))

Submission status: Accepted

Solution code:
#Lupin The 4th: O(2^n)
def f(a, b, visited):
    w = W[visited] * 20
    return float(abs(lengths[a] - lengths[b])) / (2000. / (70 + w))

def solve():
    cache = dict([((i, 0), (0., [i])) for i in xrange(n)])
    def dfs(top, visited):
        if (top, visited) in cache:
            return cache[(top, visited)]
        ret = (1 << 30, [-1])
        for i in xrange(n):
            if (visited >> i) & 1 == 1:
                tmp = dfs(i, visited ^ (1 << i))
                c = tmp[0] + f(top, i, visited)
                if c < ret[0]:
                    ret = (c, tmp[1])
        cache[(top, visited)] = (ret[0], ret[1] + [top])
        return cache[(top, visited)]
    mask = (1 << n) - 1
    ret = (1 << 30, -1)
    for i in xrange(n):
        ret = min(ret, dfs(i, mask ^ (1 << i)))
    return ret[1]

n = input()
num, lengths, weights = zip(*[map(int, raw_input().split()) for _ in xrange(n)])
cache = dict([((i, 0), 0) for i in xrange(n)])
W = [0] + [sum(weights[i] for i in xrange(n) if (b >> i) & 1 == 1)  
           for b in xrange(1, 1 << n)]
print " ".join(map(lambda i:str(num[i]), solve()))

Submission status: Accepted

Solution code:
#Lupin The 4th: O(2^n)
def f(a, b, visited):
    w = W[visited] * 20
    return float(abs(lengths[a] - lengths[b])) / (2000.0 / (70 + w))

def solve():
    cache = dict([((i, 0), (0, [i])) for i in xrange(n)])
    def dfs(top, visited):
        if (top, visited) in cache:
            return cache[(top, visited)]
        ret = (1 << 30, [-1])
        for i in xrange(n):
            if (visited >> i) & 1 == 1:
                tmp = dfs(i, visited ^ (1 << i))
                c = tmp[0] + f(top, i, visited)
                if c < ret[0]:
                    ret = (c, tmp[1])
        cache[(top, visited)] = (ret[0], ret[1] + [top])
        return cache[(top, visited)]
    mask = (1 << n) - 1
    ret = (1 << 30, -1)
    for i in xrange(n):
        ret = min(ret, dfs(i, mask ^ (1 << i)))
    return ret[1]

n = input()
num, lengths, weights = zip(*[map(int, raw_input().split()) for _ in xrange(n)])
W = [0] + [sum(weights[i] for i in xrange(n) if (b >> i) & 1 == 1)  
           for b in xrange(1, 1 << n)]
print " ".join(map(lambda i:str(num[i]), solve()))

Submission status: Accepted

Solution code:
#Lupin The 4th: O(2^n)
def f(a, b, visited):
    w = W[visited] * 20
    return float(abs(lengths[a] - lengths[b])) / (2000. / (70 + w))

def solve():
    cache = dict([((i, 0), (0., [i])) for i in xrange(n)])
    def dfs(top, visited):
        if (top, visited) in cache:
            return cache[(top, visited)]
        ret = (1 << 30, [-1])
        for i in xrange(n):
            if (visited >> i) & 1 == 1:
                tmp = dfs(i, visited ^ (1 << i))
                c = tmp[0] + f(top, i, visited)
                if c < ret[0]:
                    ret = (c, tmp[1])
        cache[(top, visited)] = (ret[0], ret[1] + [top])
        return cache[(top, visited)]
    mask = (1 << n) - 1
    ret = (1 << 30, -1)
    for i in xrange(n):
        ret = min(ret, dfs(i, mask ^ (1 << i)))
    return ret[1]

n = input()
num, lengths, weights = zip(*[map(int, raw_input().split()) for _ in xrange(n)])
W = [0] + [sum(weights[i] for i in xrange(n) if (b >> i) & 1 == 1)  
           for b in xrange(1, 1 << n)]
print " ".join(map(lambda i:str(num[i]), solve()))

Submission status: Accepted

Solution code:
n = int(input())
ids = []
dists = []
weights = []
for _ in range(n):
  s, d, v = map(int, input().split())
  ids.append(s)
  dists.append(d)
  weights.append(v * 20)

dic = {}
INF = 10 ** 20
def score(rest, pos, total_weight, order):
  if rest == 0:
    return 0, []
  if (rest, pos) in dic:
    return dic[(rest, pos)]

  mask = 1
  ret = (INF, [])
  for i in range(n):
    if rest & mask:
      temp = score(rest & ~mask, i, total_weight + weights[i], order)
      ret = min(ret, (temp[0] + abs(dists[pos] - dists[i]) / 2000 * (total_weight), [i] + temp[1]))
    mask <<= 1
  dic[(rest, pos)] = ret
  return ret

rest = 2 ** n - 1
print(*[ids[i] for i in min([score(rest, i, 70, []) for i in range(n)])[1]])

Submission status: Runtime Error

Solution code:
#Lupin The 4th: O(2^n)
def f(a, b, visited):
    w = W[visited] * 20
    return abs(lengths[a] - lengths[b]) * (70 + w)

def solve():
    cache = dict([((i, 0), (0, [i])) for i in xrange(n)])
    def dfs(top, visited):
        if (top, visited) in cache:
            return cache[(top, visited)]
        ret = (1 << 30, [-1])
        for i in xrange(n):
            if (visited >> i) & 1 == 1:
                tmp = dfs(i, visited ^ (1 << i))
                c = tmp[0] + f(top, i, visited)
                if c < ret[0]:
                    ret = (c, tmp[1])
        cache[(top, visited)] = (ret[0], ret[1] + [top])
        return cache[(top, visited)]
    mask = (1 << n) - 1
    ret = (1 << 30, -1)
    for i in xrange(n):
        ret = min(ret, dfs(i, mask ^ (1 << i)))
    return ret[1]

n = input()
num, lengths, weights = zip(*[map(int, raw_input().split()) for _ in xrange(n)])
cache = dict([((i, 0), 0) for i in xrange(n)])
W = [0] + [sum(weights[i] for i in xrange(n) if (b >> i) & 1 == 1)  
           for b in xrange(1, 1 << n)]
print " ".join(map(lambda i:str(num[i]), solve()))