zoukankan      html  css  js  c++  java
  • tsp问题

       旅行商问题(tsp问题)就是一个经销商从n个城市中的某一城市出发,不重复的走完其余的n-1个城市并回原出发点,求所有可能路径单中走出路径长度最短的一条。

     本题假设旅行商从第一个城市出发。

      解法:dfs+回溯

    #include <iostream>
    
    using namespace std;
    
    #define NUM 100
    
    int n;//图G的顶点数
    int m;//图G的边数
    int a[NUM][NUM];//图G的邻接矩阵
    int x[NUM] = {0}; //当前解
    int bestx[NUM];//最优解
    int cc = 0; //当前费用
    int bestc = 0; //当前最优值
    int NoEdge = -1; //无边标记
    int Visited[100];//访问标志
    int num = 0;
    
    int FirstArc(int t)
    {
        for(int i = 1; i <= m; i++)
            if(a[t][i] != NoEdge)
                return i;
        return 0;
    }
    
    int NextArc(int t, int w)
    {
        for(int p = w + 1; p <= m; p++)
            if(a[t][p] != NoEdge)
                return p;
        return 0;
    }
    
    void dfs(int t)
    {
        int l, i;
        Visited[t] = 1;
    
        if(num == m && a[t][1] != NoEdge)
        {
            if(cc + a[t][1] < bestc)
            {
                bestc = cc + a[t][1];
                for(int s = 0; s < m; s++)
                    bestx[s] = x[s];
            }
        }
        else
        {
            for(i = FirstArc(t); i != 0; i = NextArc(t, i))
                if(!Visited[i] && a[t][i] != NoEdge)
                    if(cc + a[t][i] < bestc) //剪枝
                    {
                        x[num++] = i;
                        cc += a[t][i];
                        dfs(i);
                        cc -= a[t][i];
                        Visited[i] = 0;
                        num--;
                    }
        }
    }
    
    void tsp(int t)
    {
        for(int i = 1; i <= m; i++)
            Visited[i] = 0;
    
        //保存第一个节点
        x[num++] = t;
        Visited[t] = 1;
    
        for(int q = FirstArc(t); q != 0; q = NextArc(t, q))
            if(a[t][q] != NoEdge && !Visited[q])
            {
                x[num++] = q;
                cc += a[t][q];
                dfs(q);
                cc -= a[t][q]; //回溯
                Visited[q] = 0;
                num--;
            }
    }
    
    
    int main()
    {
        int s, e, t;
        scanf("%d%d", &m, &n);
        //初始化邻接矩阵
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= m; j++)
                a[i][j] = NoEdge;    //表示两个节点不相连
    
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d%d", &s, &e, &t);
            a[s][e] = t;
            a[e][s] = t;
        }
        //初始化变量
        bestc = 1000;
        tsp(1);
    
        for(int i = 0; i < m; i++)
            printf("%d ", bestx[i]);
    
        printf("
    bestc=%d
    ", bestc);
        return 0;
    }
    
    /*
    1 2 20
    1 4 4
    1 3 6
    2 3 5
    2 4 10
    3 4 15
    
    */
    




  • 相关阅读:
    两个有序链表的合并
    Perl学习笔记
    生信-基本概念
    生信-序列比较dp[未完成]
    PAT 1091 Acute Stroke [难][bfs]
    PAT 1038 Recover the Smallest Number[dp][难]
    PAT 1078 Hashing[一般][二次探查法]
    PAT 1122 Hamiltonian Cycle[比较一般]
    PAT 1151 LCA in a Binary Tree[难][二叉树]
    PAT 1148 Werewolf
  • 原文地址:https://www.cnblogs.com/gaot/p/7709712.html
Copyright © 2011-2022 走看看