贪心法求TSP问题

TSP问题是指旅行家要旅行n个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。

采用最近邻点的策略
从任意城市出发,每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。

给定初始的城市a,寻找与其邻接的最短距离的城市b,记录二者之间的路径并增加总路径长度;下一次从城市b开始,寻找与b邻接的最短距离的城市,循环查找,直到找到n-1条路径(n为城市个数),最后加上终点回到起点的边即可。

代码:

#include <iostream>
#include <cstring>

using namespace std;

const int N = 105; //最多100个点
int arc[N][N];//带权矩阵
int n; //n个顶点, 从1开始
int x[N]; //结果向量
int rear = 1; //指针
//FILE *fp;

int tsp(int w)
{
    int tspLength = 0;
    int edgeCount = 0;
    int u, v, min;
    bool f[n + 1];
    memset(f, false, sizeof f);
    u = w;
    f[w] = true;

    while (edgeCount < n - 1)
    {
        min = 10000;
        for (int i = 1; i <= n; i++)
        {
            if (f[i] == false && arc[u][i] != 0 && (arc[u][i] < min))
            {
                v = i;
                min = arc[u][i];
            }
        }
        x[rear++] = v;
        tspLength += arc[u][v];
        f[v] = true;
        edgeCount++;
        u = v;
    }
    return (tspLength + arc[u][w]);
}

int main()
{
    printf("请输入城市数量n:\n");
    scanf("%d", &n);

    printf("请输入带权矩阵, 即每个城市之间的距离:\n");
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d", &arc[i][j]);

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

    printf("*********************************\n");
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
            printf("%d ", arc[i][j]);
        puts("");
    }
    puts("");

    int start;
    printf("请输入起始城市:");
    scanf("%d", &start);
    int tspLength = tsp(start);

    printf("最短路径长度为:%d\n", tspLength);

    printf("路径为:%d ->", start);

    for (int i = 1; i < rear; i++)
        printf(" %d ->", x[i]);
    printf(" %d\n", start);

    /*
    fp = fopen("TSP.txt", "w");
    if (fp == NULL)
        printf("文件打开失败!\n");
    else 
    {
        fprintf(fp, "出发城市: %d\n", start);

        fprintf(fp, "最短路径长度为:%d\n", tspLength);

        fprintf(fp, "路径为:%d ->", start);

        for (int i = 1; i < rear; i++)
            fprintf(fp, " %d ->", x[i]);
        fprintf(fp, " %d\n", start);
    }
    fclose(fp);
    */
    return 0;
}

/*
1000 3 3 2 6
3 1000 7 3 2
3 7 1000 2 5
2 3 2 1000 3
6 2 5 3 1000
*/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值