这是一个典型的旅行商问题,可以使用动态规划求解。

已知城市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 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录