巡回セールスマン問題
Traveling Salesman Problem | Aizu Online Judge
- 蟻本にものっていたやつ。
- bit DP を使う。
class traveling_salesman_problem { public: // O(2^V*V^2) void solve(void) { const int inf = (1<<30); int V, E; cin>>V>>E; vector<vector<pair<int,int>>> tree(V); REP(i, E) { int s, t, d; cin>>s>>t>>d; // dp を簡単にするため t <- s なるように登録しておく tree[t].emplace_back(s,d); } // bit DP でやる // dp[unvisited][v] := 未到達頂点が unvisited で現在位置が v のときの残りの頂点を // 全て巡回するための最小巡回コスト // vector<vector<ll>> dp((1<<V), vector<ll>(V, inf)); // 頂点 0 からスタートして全部巡回させる dp[(1<<V)-1][0] = 0; // 0 頂点を除いた全ビットからスタート for (int unvisited = (1<<V)-2; unvisited >= 0; --unvisited) { // v in S な v 毎に回る for (int v = 0; v < V; ++v) { for (const auto &e : tree[v]) { int from, cost; tie(from, cost) = e; if ( ! (unvisited & (1<<from)) ) dp[unvisited][v] = min(dp[unvisited][v], dp[unvisited|(1<<from)][from] + cost); } } } int ans = dp[0][0]; if (ans == inf) ans = -1; cout<<ans<<endl; } };