以下是一个使用暴力法(exhaustive search)解决旅行商问题的 C++ 代码,可以接受任意顶点数和边数的无向图输入:

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 20; // 最大顶点数
const int INF = 0x3f3f3f3f; // 无穷大

int n, m, ans = INF; // n为顶点数,m为边数,ans为最短路径长度
int g[MAXN][MAXN]; // 存储图的邻接矩阵
int path[MAXN]; // 存储当前路径
bool vis[MAXN]; // 标记当前顶点是否被访问过

void dfs(int u, int len, int cnt) {
    if (len >= ans) return; // 剪枝1:若当前路径长度已经超过最优解,则返回
    if (cnt == n) { // 如果所有顶点都已经访问过
        ans = len; // 更新最优解
        return;
    }
    for (int v = 0; v < n; ++v) { // 枚举下一个要访问的顶点
        if (!vis[v]) {
            vis[v] = true; // 标记为已访问
            path[cnt] = v; // 将当前顶点加入路径
            dfs(v, len + g[u][v], cnt + 1); // 递归搜索
            vis[v] = false; // 回溯,将当前顶点标记为未访问
        }
    }
}

int main() {
    ifstream fin("input.txt"); // 从文件中读入数据
    fin >> n >> m;
    memset(g, INF, sizeof(g));
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        fin >> u >> v >> w;
        g[u][v] = g[v][u] = w; // 无向图,需要同时更新两个方向的边
    }
    fin.close();
    memset(vis, false, sizeof(vis));
    vis[0] = true; // 从顶点0开始搜索
    path[0] = 0; // 将0号顶点加入路径
    dfs(0, 0, 1); // 从0号顶点开始搜索,当前路径长度为0,已经访问了1个顶点
    cout << "Shortest path length: " << ans << endl;
    cout << "Path: ";
    for (int i = 0; i < n; ++i)
        cout << path[i] << ' ';
    cout << endl;
    return 0;
}

需要注意的是,暴力法的时间复杂度是指数级别的,对于大规模的图,无法在合理的时间内求解最优解。因此,在实际应用中,需要使用其他更加高效的算法来解决旅行商问题。例如:

  • 贪婪算法: 从起点开始,每次选择距离当前位置最近的未访问节点,直到所有节点都被访问过。
  • 动态规划: 通过构建一个表格,存储从起点到每个节点的最短路径长度,并利用表格进行递推计算。
  • 模拟退火算法: 从一个随机解开始,逐步搜索更好的解,并使用一个概率函数来接受较差的解。

选择合适的算法取决于问题的规模、对解的精确度要求以及计算资源的限制。

C++ 暴力法解决旅行商问题:详解代码和优化策略

原文地址: https://www.cveoy.top/t/topic/n6AP 著作权归作者所有。请勿转载和采集!

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