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

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

class Solver
{
    void Solve()
    {
        var n = sc.Integer();
        var info = new int[n * 3];
        for (int i = 0; i < n; i++)
        {
            info[i] = sc.Integer();
            info[n + i] = sc.Integer();
            info[(n << 1) + i] = sc.Integer();
        }
        var dp = new double[1 << n, n];
        var w = new int[1 << n];
        var prev = new int[1 << n, n];

        for (int i = 0; i < 1 << n; i++)
            for (int j = 0; j < n; j++)
            {
                dp[i, j] = 1e20;
                prev[i, j] = -1;
            }
        for (int i = 0; i < 1 << n; i++)
            for (int j = 0; j < n; j++)
                if (((i >> j) & 1) == 1)
                    w[i] += info[(n << 1) + j] * 20;
        for (int i = 0; i < n; i++)
            dp[1 << i, i] = 0;

        for (int i = 0; i < 1 << n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (dp[i, j] == 1e20)
                    continue;
                if (((i >> j) & 1) == 0)
                    continue;
                for (int k = 0; k < n; k++)
                {
                    if (j == k)
                        continue;
                    if (((i >> k) & 1) == 1)
                        continue;
                    double d = Math.Abs(info[n + j] - info[n + k]);
                    var dt = d * (70 + w[i]);
                    dt /= 2000;
                    if (dp[i | 1 << k, k] > dp[i, j] + dt)
                    {
                        dp[i | 1 << k, k] = dp[i, j] + dt;
                        prev[i | 1 << k, k] = j;
                    }
                }
            }
        }
        var goal = -1;
        var cost = 1e20;
        var state = (1 << n) - 1;
        for (int i = 0; i < n; i++)
            if (cost > dp[state, i])
            {
                goal = i;
                cost = dp[state, i];
            }
        var ans = new int[n];
        ans[n - 1] = info[goal];
        for (int i = n - 2; i >= 0; i--)
        {
            var p = prev[state, goal];
            ans[i] = info[p];
            state ^= 1 << goal;
            goal = p;
        }
        Printer.PrintLine(ans);

    }
    static void Main()
    {
#if DEBUG
        var oStream = new System.IO.FileStream("debug.txt", System.IO.FileMode.Create, System.IO.FileAccess.Write);
        var iStream = new System.IO.FileStream("input.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
        Console.SetIn(new System.IO.StreamReader(iStream));
        System.Diagnostics.Debug.AutoFlush = true;
        System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(new System.IO.StreamWriter(oStream, System.Text.Encoding.UTF8)));
        try
        {
#endif
            var solver = new Solver();
            solver.Solve();
#if DEBUG
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
        Console.ReadKey(true);
#endif
    }
    _Scanner sc = new _Scanner(Console.In);

}
static public class Printer
{
    static readonly private System.IO.TextWriter writer;
    static readonly private System.Globalization.CultureInfo info;
    static string Separator { get; set; }
    static Printer()
    {
        writer = Console.Out;
        info = System.Globalization.CultureInfo.InvariantCulture;
        Separator = " ";
    }

    static public void Print(int num) { writer.Write(num.ToString(info)); }
    static public void Print(int num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(long num) { writer.Write(num.ToString(info)); }
    static public void Print(long num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(double num) { writer.Write(num.ToString(info)); }
    static public void Print(double num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(string str) { writer.Write(str); }
    static public void Print(string format, params object[] arg) { writer.Write(format, arg); }
    static public void Print(IEnumerable<char> sources) { writer.Write(sources.AsString()); }
    static public void Print(System.Linq.Expressions.Expression<Func<string, object>> expression)
    {
        var p = expression.Parameters[0];
        writer.WriteLine(p.Name);

    }

    static public void Print(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));
    }
    static public void Print<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));

    }
    static public void PrintLine(int num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(int num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(long num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(long num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(double num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(double num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(string str) { writer.WriteLine(str); }
    static public void PrintLine(string format, params object[] arg) { writer.WriteLine(format, arg); }
    static public void PrintLine(IEnumerable<char> sources) { writer.WriteLine(sources.AsString()); }
    static public void PrintLine(System.Linq.Expressions.Expression<Func<string, object>> expression)
    {
        var p = expression.Parameters[0];
        writer.WriteLine(p.Name);

    }
    static public void PrintLine(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
}
public class _Scanner
{
    readonly private System.Globalization.CultureInfo info;
    readonly System.IO.TextReader reader;
    string[] buffer = new string[0];
    int position;

    public char[] Separator { get; set; }
    public _Scanner(System.IO.TextReader reader, string separator = null, System.Globalization.CultureInfo info = null)
    {
        if (reader == null)
            throw new ArgumentNullException("reader");
        this.reader = reader;
        if (string.IsNullOrEmpty(separator))
            separator = " ";
        this.Separator = separator.ToCharArray();
        this.info = info ?? System.Globalization.CultureInfo.InvariantCulture;
    }
    public string Scan()
    {
        if (this.position < this.buffer.Length)
            return this.buffer[this.position++];
        this.buffer = this.reader.ReadLine().Split(this.Separator, StringSplitOptions.RemoveEmptyEntries);
        this.position = 0;
        return this.buffer[this.position++];
    }

    public string[] ScanToEndLine()
    {
        if (this.position >= this.buffer.Length)
            return this.reader.ReadLine().Split(this.Separator, StringSplitOptions.RemoveEmptyEntries);
        var size = this.buffer.Length - this.position;
        var ar = new string[size];
        Array.Copy(this.buffer, position, ar, 0, size);
        return ar;

    }

    public string ScanLine()
    {
        if (this.position >= this.buffer.Length)
            return this.reader.ReadLine();
        else
        {
            var sb = new System.Text.StringBuilder();
            for (; this.position < buffer.Length; this.position++)
            {
                sb.Append(this.buffer[this.position]);
                sb.Append(' ');
            }
            return sb.ToString();
        }
    }
    public string[] ScanArray(int length)
    {
        var ar = new string[length];
        for (int i = 0; i < length; i++)
        {
            ar[i] = this.Scan();
        }
        return ar;
    }

    public int Integer()
    {
        return int.Parse(this.Scan(), info);
    }
    public long Long()
    {
        return long.Parse(this.Scan(), info);
    }
    public double Double()
    {
        return double.Parse(this.Scan(), info);
    }
    public double Double(string str)
    {
        return double.Parse(str, info);
    }

    public int[] IntArray(int length)
    {
        var a = new int[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Integer();
        return a;
    }
    public long[] LongArray(int length)
    {
        var a = new long[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Long();
        return a;
    }
    public double[] DoubleArray(int length)
    {
        var a = new double[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Double();
        return a;
    }

}
static public partial class EnumerableEx
{
    static public string AsString(this IEnumerable<char> source)
    {
        return new string(source.ToArray());
    }
    static public T[] EnumerateArray<T>(this int count, Func<int, T> selector)
    {
        var ret = new T[count];
        for (int i = 0; i < count; i++)
            ret[i] = selector(i);
        return ret;
    }
}

//*/