問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!
巡回セールスマン問題とは、都市の集合と各都市間の距離が与えられ、全都市をちょうど1回ずつ訪れたのち出発した都市に戻ってくるような経路 (巡回路) のうち最も短いものを求める問題です。
ここでは、2-opt 法と呼ばれるアルゴリズムを学習しましょう。このアルゴリズムは発見的解法 (ヒューリスティクス) と呼ばれるもので、ある程度良い解が出力されることが期待されるものの、解の精度は全く保証されません。
2-opt 法の概要は、以下の通りです。
・ 巡回路を適当に作り、初期解とする
・ 一定の回数か、解があまり改善されなくなるまで以下を繰り返す
・ 巡回路を成す辺を 2 本選び、その辺をつなぎ変えることを考える。つなぎ変えることによって巡回路長が短くなるならつなぎ変える。短くならないなら何もしない
dist(a, d) + dist(b, c) > dist(a, b) + dist(c, d)
が成り立つため、辺をつなぎ変えます。Yes
と出力し、2 行目以降に辺をつなぎ変えた巡回路を出力してください。短くならない場合は 1 行目にNo
と出力してください。n
x_0 y_0
x_1 y_1
...
x_{n-1} y_{n-1}
p_0
p_1
...
p_{n-1}
a b
出力は n+1 行または 1 行です。辺をつなぎ変えることによって巡回路長が短くなる場合は 1 行目にYes
と出力し、2 行目以降に辺をつなぎ変えた巡回路を出力してください。巡回路は都市番号 (0, 1, ... , n-1) の順列で表し、都市番号を先頭から順に各行に 1 つずつ出力してください。辺をつなぎ変えても巡回路長が短くならない場合は 1 行にNo
と出力してください。
すべてのテストケースにおいて、以下の条件をみたします。
・ 入力はすべて整数
・ 4 ≦ n ≦ 3,000
・ -1,000 ≦ x_i, y_i ≦ 1,000 (0 ≦ i ≦ n-1)
・ i ≠ j ならば (x_i, y_i) ≠ (x_j, y_j)
・ p は {0, 1, ... , n-1} を並べ替えた順列
・ 0 ≦ a < b ≦ n-1
・ a+1 < b
・ a = 0 のとき、b != n-1
4
0 0
2 2
-1 1
1 -1
1
2
3
0
1 3
Yes
0
2
1
3
4
0 0
2 2
-1 1
1 -1
1
3
0
2
0 2
No