巡回セールスマン問題
\(N\)個のノード\(1, 2, ..., N\)を持つ重み付き有向グラフ\(G(V, E)\)について,ノード\(1\)から出発し,各ノードをちょうど1度ずつ通りノード\(1\)へ戻る閉路の中で最短の経路の距離を求めよ.
この問題はNP困難というクラスに属する有名な問題で,多項式時間で解くアルゴリズムが存在しないとされている.bitDPというアルゴリズムを使うと,\(O(|V|^22^{|V|})\)で解くことができる.
具体的には以下の漸化式が成立する.
$$ dp[\mathbb{S}][v] = min_{u \in (\mathbb{S}\backslash \lbrace v \rbrace)}(dp[S\backslash \lbrace v \rbrace][u] + dist[u][v]) $$
自然言語でいうなら,「今まで訪れたノードの集合が\(\mathbb{S}\)で最後に訪れたノードが\(v\)になるような最短経路は,今までノードの集合が\(\mathbb{S}\backslash \lbrace v \rbrace\)で最後に訪れたノードが\(\mathbb{S}\backslash \lbrace v \rbrace\)に含まれるいずれかのノードであるような最短経路にそのノードから\(v\)への距離を足した値の最小値」.
この訪れたノードの集合をbitで持つ.この集合の状態数は\(2^|V|\)となり,最後に訪れたノードの状態数は\(|V|\)である.各状態から,次に通る都市を\(|V|\)通り探索するので,全体の計算量は\(O(|V|^22^{|V|})\)となる.
コード
i64 tsp(int n, vector<vector<int>> &dist) {
vector<vector<i64>> dp(1<<n, vector(n, inf));
dp[0][0] = 0;
rep (bit, 1<<n) {
rep (u, n) {
if (!((bit >> u)&1) and bit + u != 0) continue;
rep (v, n) {
if ((bit >> v)&1) continue;
chmin(dp[bit|(1<<v)][v], dp[bit][u] + dist[u][v]);
}
}
}
return dp[(1<<n)-1][0];
}