利用贪心算法求解TSP问题(C语言实现)

1 TSP问题简介

  • 旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
    在这里插入图片描述
  • TSP的数学模型为:
    在这里插入图片描述

2 贪心算法简介

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

3 贪心算法应用于TSP问题

  • 贪心算法是一种算法策略,或者说问题求解的策略。基本思想是“今朝有酒今朝醉”。即一定要做当前情况下的最好选择,否则将来可能后悔,故名“贪心”。
  • 将贪心算法应用于TSP问题中的求解思想:从某一个城市开始,每次选择一个城市,知道所有城市都被走完。注:每次在选择下一个城市的时候,只考虑当前情况,保证迄今为止经过的路径的总距离最短。

4 C程序流程图(参考战德臣老师)

在这里插入图片描述

5 C程序代码实现贪心算法求解TSP问题

#include <stdio.h>
#define n 4

int main(void) {
	int Dis[n][n], City[n], Sum, i, j, k, l, Dtmp, Found;
	City[0] = 0;
	Sum = 0;
	Dis[0][1] = 2; Dis[0][2] = 1; Dis[0][3] = 5; Dis[1][0] = 2; Dis[1][2] = 4;
	Dis[1][3] = 4; Dis[2][0] = 1; Dis[2][1] = 4; Dis[2][3] = 6; Dis[3][0] = 5;
	Dis[3][1] = 4; Dis[3][2] = 6;

	for (i = 1; i < n; i++) {
		Dtmp = 10000;                    
		for (k = 1; k < n; k++) {
			Found = 0;
			for (l = 0; l < i; l++) {
				if (City[l] == k) {
					Found = 1;
					break;
				}
			}
			if (Found == 0 && Dis[City[i - 1]][k] < Dtmp) {
				j = k;
				Dtmp = Dis[City[i - 1]][k];
			}
		}
		City[i] = j;
		Sum = Sum + Dtmp;
	}

	Sum = Sum + Dis[j][0];
	for (i = 0; i < n; i++) {
		printf("%d\t", City[i]);
	}
	printf("\n");
	printf("Sum = %d", Sum);

	getchar();
}

5.1 变量说明:

  • 城市映射为编号:A-0, B-1, C-2, D-3。
  • 数组Dis[n][n]用于存储城市之间的距离关系。
  • 数组City[n]用来存储实现距离最短的依次访问的城市代号顺序。
  • Sum用来存储最终的最短距离。
  • Dtmp用于存储临时的一个最短距离。
  • Found用来判定第k个城市是否是已经访问过的城市。
  • i表示第i次将要访问的城市。City[i]即第i次要访问的城市的代号。
  • j用来存储已确定的第i次要访问的城市代号j。
  • k用来存储第i次可能要访问的城市的代号。
  • l表示前几次已经访问过的城市。City[l]即第l次访问过的城市的代号。

5.2 程序流程说明

  • 声明变量
  • 设定起点城市,即第0次访问的城市代号为0。
  • 初始化Sum的值为0。
  • 导入城市距离矩阵。
  • 进入循环:
  • 外层循环:从i=1开始循环,i小于n, 初始化最短距离为10000(取一个大值,使其至少大于城市距离矩阵中的最大值)。即首先求出第1次将要访问的城市代号(利用中层循环及内层循环求解),然后将求出的第1次将要访问的城市代号j赋值给City[1],并将当前城市(代号0)至代号为j的城市的距离Dtmp累加至Sum。直至求出第n-1次要访问的城市代号。
  • 中层循环:从k=1开始循环,k小于n,初始化Found的值为0。即先假设第i次要访问的城市代号为1,并判断代号为1的城市有没有出现在前几次访问过的城市中(利用内层循环判断),如果代号为1的城市没有出现在已经访问过的城市中并且当前城市(代号i-1)至代号为1的城市的距离小于Dtmp,那就把k=1的值赋值给j,再把当前城市(代号i-1)至代号为1的城市的距离赋值给Dtmp。直至循环到代号为n-1的城市,这样就能根据局部最短距离求出下一个城市的代号i与距离Dtmp。
  • 内层循环:从l=0开始循环,l小于i,判断第l次访问过的城市代号是否与k的值相等,如果相等,代表第l次已经访问过代号为k的城市了,那么就将Found值置1,跳出循环。直至判断完第i-1次访问过的城市。
  • 循环结束。
  • 将第n-1次要访问的代号为j的城市到起点城市的距离累加至Sum。
  • 输出访问城市的代号次序。
  • 输出最短距离。
贪心算法是一种算法策略,它在解决问题时总是做出在当前看来是最好的选择。贪心算法不一定能得到整体最优解,但可以得到局部最优解。对于TSP问题旅行问题),贪心算法可以应用于求解思想。其基本思想是从某一个城市开始,每次选择一个最近的城市,直到所有的城市都被走过一遍,并确保经过的路径总距离最短。这种贪心策略称为最近邻点策略。最近邻点策略的算法设计如下:从某城市出发,每次在未经过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。这个算法的时间复杂度为O(n^2),因为每次选择都需要查找满足贪心条件的最短边。然而,最近邻点策略无法保证得到最优解,尤其是当图中顶点较多且边的代价值分布不均匀时。在这种情况下,最近邻点策略只能给出较好的近似解,但无法保证近似程度。另一种贪心策略是最短链接策略。它的思想是在整个图的范围内选择最短边加入解集合,同时要保证加入解集合的边最终形成一个哈密顿回路。最短链接策略的算法设计如下:每次从剩余边集合中选择最短的边加入解集合,同时满足边是剩余边集合中代价最小的边、加入解集合后不产生回路和分枝。同样地,最短链接策略也不能保证得到最优解。因此,贪心算法可以用于求解TSP问题,但结果可能只是近似解,并不一定是最优解。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [利用贪心算法求解TSP问题(C语言实现)](https://blog.csdn.net/mahoon411/article/details/105940729)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [数学建模贪心算法(贪婪算法)求解TSP问题(C语言程序源码亲测可行)](https://download.csdn.net/download/mahoon411/12393733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [用贪心法解决TSP问题](https://blog.csdn.net/wmy01234/article/details/106020551)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吮指原味张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值