回溯法--旅行商问题

题目描述

给定无向图G(N,E),含有n个结点,m条边。现在有以下定义:
有一个商人从1号结点出发,希望经过每个结点一次回到起点,并且他希望走权值最小的一条路径。
输入第一行2个整数n,m;
接下来m行,每行三个数,u,v,w表示u,v结点有一条权值为w的无向边。
如果不存在这种路径,打印 -1;
否则打印两行。
第一行一个整数代表最优值,第二行n+1个点表示路径经过村庄的顺序,若答案不唯一,打印任意一个即可。

题目模型

  • 未完待续

题目代码

/*
3 3
1 2 2
1 3 4
2 3 10

16
1 2 3 1
*/
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 10;

int n;              // 图G的顶点数
int x[N];           // 当前解
int bestx[N];       // 当前最优解
int a[N][N];        // 图G的邻接矩阵
int cc;             // 当前费用
int bestc;          // 当前最优值
int NoEdge;         // 无边标记

void Backtrack(int i)
{
    if(i == n)
    {
        if(a[x[n - 1]][x[n]] != NoEdge && a[x[n]][1] != NoEdge &&
                (cc + a[x[n - 1]][x[n]] + a[x[n]][1] < bestc || bestc == NoEdge))
        {
            for(int j = 1; j <= n; j ++ )
                bestx[j] = x[j];
            bestc = cc + a[x[n - 1]][x[n]] + a[x[n]][1];
        }
    }
    else
    {
        for(int j = i; j <= n; j ++ )
        {
            // 是否可进入x[j]子树
            if(a[x[i - 1]][x[j]] != NoEdge && (cc + a[x[i - 1]][x[j]] < bestc || bestc == NoEdge))
            {
                // 搜索子树
                swap(x[i], x[j]);
                cc += a[x[i - 1]][x[i]];
                Backtrack(i + 1);
                cc -= a[x[i - 1]][x[i]];
                swap(x[i], x[j]);
            }
        }
    }
}

int main()
{
    int m;
    cin >> n >> m;
    for(int i = 1; i <= m; i ++ )
    {
        int u, v, w;
        cin >> u >> v >> w;
        a[u][v] = a[v][u] = w;
    }

    for(int i = 1; i <= n; i ++ ) x[i] = i;

    Backtrack(2);

    cout << "最优值为:" << bestc << endl;
    for(int i = 1; i <= n; i ++ )
        cout << bestx[i] << " ";
    cout << "1" << endl;
    
    return 0;
} 

posted @   esico  阅读(241)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示