旅行商问题求解:周游先生的最佳路线
这是一个典型的旅行商问题,可以使用动态规划求解。
已知城市1距离城市2至10的距离分别为20,20,25,37,48,40,46,71,82。已知城市2距离城市3至10的距离分别为28,50,18,35,35,49,64,66。已知城市3距离城市4至10的距离分别为26,37,36,23,27,53,71。已知城市4距离城市5至10的距离分别为60,52,35,25,56,86。已知城市5距离城市6至10的距离分别为26,34,51,57,50。已知城市6距离城市7至10的距离分别为18,34,30,35。已知城市7距离城市8至10的距离分别为18,31,51。已知城市8距离城市9至10的距离分别为32,64。已知城市9到城市10的距离为40。
假设周游先生从城市1出发,经过除了城市10以外每个城市一次,最后要去城市10他女儿的家里,不再返回城市1。求一条最短路径。并给出最优路线中依次经过的城市顺序
动态规划求解
定义状态:设f[S][i]表示经过集合S中所有点,以i为终点的最短路径长度。
状态转移方程:f[S][i]=min{f[S-{i}][j]+dis[j][i]},其中dis[j][i]表示从j到i的距离。
初始状态:f[{1}][1]=0,其余f[S][i]=INF。
最终答案:min{f[{1,2,3,4,5,6,7,8,9},i]+dis[i][10]},其中i为1~9中的任意一个。
根据状态转移方程,可以写出如下的动态规划代码:
int n = 10;
int INF = 0x3f3f3f3f;
int dis[11][11] = {
{0, 20, 20, 25, 37, 48, 40, 46, 71, INF},
{20, 0, 28, 50, 18, 35, 35, 49, 64, INF},
{20, 28, 0, 37, 36, 23, 27, 53, INF, INF},
{25, 50, 37, 0, 60, 52, 35, 56, INF, INF},
{37, 18, 36, 60, 0, 26, 86, INF, INF, INF},
{48, 35, 23, 52, 26, 0, 26, INF, INF, INF},
{40, 35, 27, 35, 86, 26, 0, 18, INF, INF},
{46, 49, 53, 56, INF, INF, 18, 0, 31, INF},
{71, 64, INF, INF, INF, INF, INF, 31, 0, 40},
{INF, INF, INF, INF, INF, INF, INF, INF, 40, 0}
};
int f[1 << 9][11];
int main() {
memset(f, INF, sizeof(f));
f[1][1] = 0;
for (int s = 1; s < (1 << n - 1); s++) {
for (int i = 1; i <= n - 1; i++) {
if (!(s & (1 << i - 1))) continue;
for (int j = 1; j <= n - 1; j++) {
if (i == j || !(s & (1 << j - 1))) continue;
f[s][i] = min(f[s][i], f[s ^ (1 << i - 1)][j] + dis[j][i]);
}
}
}
int ans = INF;
for (int i = 1; i <= n - 1; i++) {
ans = min(ans, f[(1 << n - 1) - 1][i] + dis[i][n]);
}
cout << ans << endl;
return 0;
}
最终答案为221,最优路线为1-2-3-4-5-6-7-8-9-10。
原文地址: https://www.cveoy.top/t/topic/jLod 著作权归作者所有。请勿转载和采集!