Official
E - 配送ルートの最適化 / Optimization of Delivery Routes Editorial
by
E - 配送ルートの最適化 / Optimization of Delivery Routes Editorial
by
physics0523
この問題は、典型的な 巡回セールスマン問題(TSP) の一例です。
巡回セールスマン問題は NP 困難 であるため多項式時間で解くことは困難ですが、時間計算量 \(O(2^NN^2)\) で解く方法があります。
bitDP を用いてこの問題を解くことができます。
bitDP の解説は以下の記事を参照できるほか、インターネット上に多くの解説が存在します。
bitDP を行う際、予め距離行列 ( つまり、 \(d_{i,j} = \) \(i\) から \(j\) に直接移動する際の距離 ) を求めておくと高速化できる場合があります。
なお、本問題では (地点の添え字を \(0\) 始まりにするものとして) \(dp[2^k][k] = d_{0,k}\) と初期化した上で、 \(dp[2^N-1][0]\) を答えとするとスマートに実装できます。
このようにすることで、 \(0\) から地点 \(k\) に移動するのにかかるコストで初期化され、 \(k\) から始めて全ての地点を \(1\) 度ずつ通った時に最後に地点 \(0\) を通る場合を抽出することができます。これは、 \(0\) から始めて全頂点を回って \(0\) に戻るサイクルに対応します。
時間計算量は \(O(2^NN^2)\) です。
実装例 (C++):
#include<bits/stdc++.h>
using namespace std;
int main(){
int N;
cin >> N;
vector<int> X(N),Y(N);
for(int i=0;i<N;i++){
cin >> X[i] >> Y[i];
}
vector<vector<int>> d(N,vector<int>(N,1e9));
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
d[i][j]=(X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]);
}
}
vector<vector<int>> dp(1<<N,vector<int>(N,1e9));
for(int i=1;i<N;i++){
dp[(1<<i)][i]=d[0][i];
}
for(int i=0;i<(1<<N);i++){
for(int j=0;j<N;j++){
if(dp[i][j]>5e8){continue;}
for(int k=0;k<N;k++){
if(i&(1<<k)){continue;}
dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+d[j][k]);
}
}
}
cout << dp[(1<<N)-1][0] << "\n";
return 0;
}
posted:
last update:
