算法报告旅行商问题模板

合集下载

算法分析与设计总报告

算法分析与设计总报告

算法分析与设计上级实现题报告TSP问题一、问题描述所谓TSP问题是指旅行商要去n个城市推销商品,其中每个城市到达且仅到达一次,并且要求所走的路程最短(该问题又称货郎担问题、邮递员问题、售货员问题等)。

TSP问题最容易想到、也肯定能得到最优解的算法是穷举法,即考察所有可能的行走线路,从中选出最佳的一条。

二、解题思路1.基木思路对于图G=(V,E),从起点出发,其余点作为路径集合,然后列出路径集合中各个点作为子路径起点,其余点作为路径集合的情况,从中选取路径长度最短的情况,再对路径集合迭代计算,直到路径集合为空的时候,这时最短路径的情况即是该点到原点的距离,路径集合是空集{},此时己触碰临界条件,可以不断回溯之前的迭代,进而解决此问题。

2.最优值函数和边界条件rd(k,o)= ckild(i,W) = minfCjk + d(k V - {k}) } (k G V z) 第二行是最优值函数。

从i到集合v的最优路径是以v'中某一点作为子路径起点,其余点作为路径集合的路径的长度加上从k至ij i 的距离的最优值。

第一行是边界条件。

当子路径的路径集合是空集时,最优子问题的解,木题来说也就是子路径的最短路径就是从子路径的起点到原来起点的距离。

3.标记函数标记函数同时也是算法的核心函数,完全按照递推公式的思想,使用迭代的方式。

distance是第一个核心函数,主要负责路径的输岀; distance 1是第二个核心函数,主要负责寻求子集合的最短路径并计算长度。

第一核心函数中调用了第二核心函数,第一核心函数只负路径的输出,在将问题细化深入的过程中,将真正的路径寻找和计算交给第二核心函数。

4.标记函数的解读:(l)distancedouble distance(int a^int b[]^int double d[][NUM]^int start) a:子问题起点b[]:字问题路径集合d[][]:距离矩阵(最开始创建的,所有调用函数过程中,都使用的这个,没有更改,只有读取)start:原问题起点(达到临界条件时,找到路径长度)〃边界条件if(c==0){cout<<start;return d[a][start];}〃非临界条件时候,构建所有路径集合的,起点和对应的路径集合,在迭代的时候会使用到else{for(i=0;i<c;i++){point[i]=b[i];k=0;for(j=0;j<c;j++){e[i][k]=b[j]; /*节点方阵,冗余的*/k++;}}}mindistance=distancel(point[k]^efkj^c-l^d^start)+d[a][point[k] ];〃假定下一层的最短路径就是p[0]以及其对应的路径矩阵e[k] for(i=0;i<c-l;i++) //比较出下一层真正的最短路径if (mindis tan ce>(dis tan cel(po int[ i+1] star t)+d[ a][point[i+l]])){k=i+l;mindistance=distancel(point[灯,e[k],c-l’d,start)+d[a][poin t[k]];}cout<<point[k]<<,l->";return distance(point[k],e[k],c-l’d,start)+d[a][point[k]];}(2)distanceldouble distancel(int a,int b[],int c^double d[][NUMj^int start) 〃边界条件if(c==0){return d[a][start];}〃非边界条件else{for(i=0;i<c;i++){point[i]=b[i];k=0;for(j=0;j<c;j++){e[i][k]=b[j];k++;}}}//拆分该点到达起点所需经过的集合该点的下一点到达起点所需经过的集合mindistance=distancel(point [0],e[0] start)+d[a] [point [ 0]];for(i=0;i<c-l;i++)if (mindis tan ce>(dis tancel (point [i+1] ,e[i+:L]’c-:La star t) +d[ a][point[i+l]]))mindistance=distancel(point[i+l],e[i+l],c-:Lsd,start)+d[a][ point]i+1]];return mindistanee; 〃求最小值}}5.时间复杂度分析整体的时间复杂度是O (2M)。

实验六:遗传算法求解TSP问题实验2篇

实验六:遗传算法求解TSP问题实验2篇

实验六:遗传算法求解TSP问题实验2篇第一篇:遗传算法的原理与实现1. 引言旅行商问题(TSP问题)是一个典型的组合优化问题,它要求在给定一组城市和每对城市之间的距离后,找到一条路径,使得旅行商能够在所有城市中恰好访问一次并回到起点,并且总旅行距离最短。

遗传算法作为一种生物启发式算法,在解决TSP问题中具有一定的优势。

本实验将运用遗传算法求解TSP问题,以此来探讨和研究遗传算法在优化问题上的应用。

2. 遗传算法的基本原理遗传算法是模拟自然界生物进化过程的一种优化算法。

其基本原理可以概括为:选择、交叉和变异。

(1)选择:根据问题的目标函数,以适应度函数来评估个体的优劣程度,并按照适应度值进行选择,优秀的个体被保留下来用于下一代。

(2)交叉:从选出的个体中随机选择两个个体,进行基因的交换,以产生新的个体。

交叉算子的选择及实现方式会对算法效果产生很大的影响。

(3)变异:对新生成的个体进行基因的变异操作,以保证算法的搜索能够足够广泛、全面。

通过选择、交叉和变异操作,不断迭代生成新一代的个体,遗传算法能够逐步优化解,并最终找到问题的全局最优解。

3. 实验设计与实施(1)问题定义:给定一组城市和每对城市之间的距离数据,要求找到一条路径,访问所有城市一次并回到起点,使得旅行距离最短。

(2)数据集准备:选择适当规模的城市数据集,包括城市坐标和每对城市之间的距离,用于验证遗传算法的性能。

(3)遗传算法的实现:根据遗传算法的基本原理,设计相应的选择、交叉和变异操作,确定适应度函数的定义,以及选择和优化参数的设置。

(4)实验流程:a. 初始化种群:随机生成初始种群,每个个体表示一种解(路径)。

b. 计算适应度:根据适应度函数,计算每个个体的适应度值。

c. 选择操作:根据适应度值选择一定数量的个体,作为下一代的父代。

d. 交叉操作:对父代进行交叉操作,生成新的个体。

e. 变异操作:对新生成的个体进行变异操作,以增加搜索的多样性。

实验六:遗传算法求解TSP问题实验3篇

实验六:遗传算法求解TSP问题实验3篇

实验六:遗传算法求解TSP问题实验3篇以下是关于遗传算法求解TSP问题的实验报告,分为三个部分,总计超过3000字。

一、实验背景与原理1.1 实验背景旅行商问题(Traveling Salesman Problem,TSP)是组合优化中的经典问题。

给定一组城市和每两个城市之间的距离,求解访问每个城市一次并返回出发城市的最短路径。

TSP 问题具有很高的研究价值,广泛应用于物流、交通运输、路径规划等领域。

1.2 遗传算法原理遗传算法(Genetic Algorithm,GA)是一种模拟自然选择和遗传机制的搜索算法。

它通过选择、交叉和变异操作生成新一代解,逐步优化问题的解。

遗传算法具有全局搜索能力强、适用于多种优化问题等优点。

二、实验设计与实现2.1 实验设计本实验使用遗传算法求解TSP问题,主要包括以下步骤:(1)初始化种群:随机生成一定数量的个体(路径),每个个体代表一条访问城市的路径。

(2)计算适应度:根据路径长度计算每个个体的适应度,适应度越高,路径越短。

(3)选择操作:根据适应度选择优秀的个体进入下一代。

(4)交叉操作:随机选择两个个体进行交叉,生成新的个体。

(5)变异操作:对交叉后的个体进行变异,增加解的多样性。

(6)更新种群:将新生成的个体替换掉上一代适应度较低的个体。

(7)迭代:重复步骤(2)至(6),直至满足终止条件。

2.2 实验实现本实验使用Python语言实现遗传算法求解TSP问题。

以下为实现过程中的关键代码:(1)初始化种群```pythondef initialize_population(city_num, population_size): population = []for _ in range(population_size):individual = list(range(city_num))random.shuffle(individual)population.append(individual)return population```(2)计算适应度```pythondef calculate_fitness(population, distance_matrix): fitness = []for individual in population:path_length =sum([distance_matrix[individual[i]][individual[i+1]] for i in range(len(individual) 1)])fitness.append(1 / path_length)return fitness```(3)选择操作```pythondef selection(population, fitness, population_size): selected_population = []fitness_sum = sum(fitness)fitness_probability = [f / fitness_sum for f in fitness]for _ in range(population_size):individual = random.choices(population, fitness_probability)[0]selected_population.append(individual)return selected_population```(4)交叉操作```pythondef crossover(parent1, parent2):index1 = random.randint(0, len(parent1) 2)index2 = random.randint(index1 + 1, len(parent1) 1)child1 = parent1[:index1] +parent2[index1:index2] + parent1[index2:]child2 = parent2[:index1] +parent1[index1:index2] + parent2[index2:]return child1, child2```(5)变异操作```pythondef mutation(individual, mutation_rate):for i in range(len(individual)):if random.random() < mutation_rate:j = random.randint(0, len(individual) 1) individual[i], individual[j] = individual[j], individual[i]return individual```(6)更新种群```pythondef update_population(parent_population, child_population, fitness):fitness_sum = sum(fitness)fitness_probability = [f / fitness_sum for f in fitness]new_population =random.choices(parent_population + child_population, fitness_probability, k=len(parent_population)) return new_population```(7)迭代```pythondef genetic_algorithm(city_num, population_size, crossover_rate, mutation_rate, max_iterations): distance_matrix =create_distance_matrix(city_num)population = initialize_population(city_num, population_size)for _ in range(max_iterations):fitness = calculate_fitness(population, distance_matrix)selected_population = selection(population, fitness, population_size)parent_population = []child_population = []for i in range(0, population_size, 2):parent1, parent2 = selected_population[i], selected_population[i+1]child1, child2 = crossover(parent1, parent2)child1 = mutation(child1, mutation_rate)child2 = mutation(child2, mutation_rate)parent_population.extend([parent1, parent2]) child_population.extend([child1, child2])population =update_population(parent_population, child_population, fitness)best_individual =population[fitness.index(max(fitness))]best_path_length =sum([distance_matrix[best_individual[i]][best_individual[i +1]] for i in range(len(best_individual) 1)])return best_individual, best_path_length```三、实验结果与分析3.1 实验结果本实验选取了10个城市进行测试,遗传算法参数设置如下:种群大小:50交叉率:0.8变异率:0.1最大迭代次数:100实验得到的最佳路径长度为:1953.53.2 实验分析(1)参数设置对算法性能的影响种群大小:种群大小会影响算法的搜索能力和收敛速度。

旅行商问题资料

旅行商问题资料

算法设计与分析实验报告实验三旅行商问题院系:班级:计算机科学与技术学号:姓名:任课教师:成绩:湘潭大学2016年5月实验三旅行商问题一. 实验内容分别编程实现回溯法和分支限界法求TSP问题的最优解,分析比较两种算法的时间复杂度并验证分析结果。

二.实验目的1、掌握回溯法和分支限界法解决问题的一般步骤,学会使用回溯法和分支限界法解决实际问题;2、理解回溯法和分支限界法的异同及各自的适用范围。

三. 算法描述旅行商问题的回溯法算法可描述如下:Template <class Type>Class Traveling{friend Type TSP(int ** , int[],int ,Type);Private;Void Backtrack(int i);Int n, //图G的顶点数*x; //当前解*bestx; //当前最优解Type **a, //图G的邻接矩阵cc, //当前费用bestc,//当前最优解NoEdge; //无边标记};Template <class Type>Void Traveling<Type> : : 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] +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]);}}}Template<class Type>Type TSP(Type**a, int v[], int n, Type NoEdge){Traveling<Type> Y;//初始化YY.x = new int [n+1];//置x为单位排列For(int i = 1;i <= n;i++)Y.x[i] = i;Y.a = a;Y.n = n;Y.bestc = NoEdge;Y.bestx = v; = 0;Y.NoEdge = NoEdge;//搜索x[2:n]的全排列Y.Backtrack(2);Delete[]Y.x;Return Y.bestc;}算法效率:如果不考虑更新bestx所需的计算时间,则Backtrack需要O((n-1)!)计算时间。

A星算法求解旅行商问题(可打印修改)

A星算法求解旅行商问题(可打印修改)

int size = str_arr.length; int[] int_arr = new int[size];
for(int i = 0; i < size; i ++){ int_arr[i] = Integer.valueOf(str_arr[i]);
}
return int_arr; }
//获取所有路径中最短的路径 private int get_min_distance(){
FileInputStream fi = new FileInputStream(file);
InputStreamReader ir = new InputStreamReader(fi);
BufferedReader br = new BufferedReader(ir);
//------------------------------------
城市之间的距离:通过 n*n 矩阵 city_distance 表示,其中 n 表示城市的个数。编号为 k 的城市到各个城市之间的距离可以从第(k-1)行获取。
open 表:用队列表示,城市结点进入队列之前需要根据估计值 fvalue 按升序排列。
close 表:用向量表示。 搜索图:搜索图通过 open 表构建,将路径的编号保存在一个数组 id_list 中。 四、实验结果和分析 1、输入数据 第一行的数Байду номын сангаас 8 表示城市结点的个数,后面是一个 8*8 的数组,数组的值表示城市之 间的距离。任何一个结点到自身的距离是 0,数组中的第 0 行表示第 1 个城市到各个城市 之间的距离,其他的可类推。
Astar 算法求解旅行商问题
一、问题描述 一共有 n 个城市,某推销员从其中的一个城市 A 出发经过每个城市一次且仅一次后回

图算法--旅行商问题

图算法--旅行商问题

图算法--旅⾏商问题旅⾏商问题的描述试想⼀下,⼀个业务员因⼯作需要必须访问多个城市。

他的⽬标是每个城市只访问⼀次,并且尽可能地缩短旅⾏的距离,最终返回到他开始旅⾏的地点,这就是旅⾏商问题的主要思想。

在⼀幅图中,访问每个顶点⼀次,并最终返回起始顶点,这个访问的轨迹称为哈密顿圈。

要解决旅⾏商问题,需要⽤图G=(V,E)作为模型,寻找图中最短的哈密顿圈。

G是⼀个完整的、⽆⽅向的带权图,其中V代表将要访问的顶点的集合,E为连接这些顶点的边的集合。

E中每条边的权值由顶点之间的距离决定。

由于G中⼀个完整的、⽆⽅向的图,因此E包含V(V-1)/2条边。

事实上,旅⾏商问题是⼀种特殊的⾮多项式时间问题,称为NP完全问题。

NP完全问题是指那些多项式时间算法未知,倘没有证据证明没有解决的可能性的问题。

考虑到这种思想,通常⽤⼀种近似算法来解决旅⾏商问题。

最近邻点法的应⽤⼀种近似的计算旅⾏商路线的⽅法就是使⽤最近邻点法。

其运算过程如下:从⼀条仅包含起始顶点的路线开始,将此顶点涂⿊。

其他顶点为⽩⾊,在将其他顶点加⼊此路线中后,再将相应顶点涂⿊。

接着,对于每个不在路线中的顶点v,要为最后加⼊路线的顶点u与v之间的边计算权值。

在旅⾏商问题中,u与v之间边的权值就是u到v 之间的距离。

这个距离可以⽤每个顶点的坐标计算得到。

两个点(x1,y1)与(x2,y2)之间距离的计算公式如下:r = √(x2 - x1)2 + (y2 - y1)2 (注意是求和的平⽅根)利⽤这个公式,选择最接近u的顶点,将其涂⿊,同时将其加⼊路线中。

接着重复这个过程,直到所有的顶点都涂成⿊⾊。

此时再将起始顶点加⼊路线中,从⽽形成⼀个完整的回路。

下图展⽰了使⽤最近邻点法来解决旅⾏商问题的⽅法。

通常,在为旅⾏商问题构造⼀个图时,每个顶点之间相连的边不会显⽰表⽰出来,因为这种表⽰会让图不清晰了,也没有必要。

在图中,每个顶点旁边都显⽰其坐标值,虚线表⽰在此阶段需要⽐较距离的边。

旅行商问题的两种算法的开题报告

旅行商问题的两种算法的开题报告

旅行商问题的两种算法的开题报告开题报告题目:旅行商问题的两种算法探究目的及意义:旅行商问题是指旅行商沿着多个城市行走,每个城市只访问一次,最终回到起点,使得总路程最短。

这是一个NP难问题,在实际应用中经常出现,如物流、旅游等领域。

因此,研究旅行商问题的算法及其性能优化,对提高实际应用的效率具有重要的意义。

本文将探究旅行商问题的两种算法:遗传算法和模拟退火算法。

两种算法均为常用的启发式算法,有较好的性能表现。

研究它们的原理、优点、缺点及其在旅行商问题中的应用,旨在提供一种有效的解决旅行商问题的思路。

研究内容及方法:本文将从以下几个方面研究旅行商问题的两种算法:1.算法原理解析:对遗传算法和模拟退火算法进行详细的原理解析,分析它们的实现过程和流程。

2.优点和缺点分析:对遗传算法和模拟退火算法的优点和缺点进行分析,提出改进措施。

3.算法性能比较:通过实验,比较两种算法的性能表现。

使用实际的数据集,分别运行两种算法,并对各种因素进行分析。

4.算法应用探讨:将两种算法应用到实际问题中,如物流配送或旅游路线规划,比较它们的效率和优劣,以及应用场景的不同之处。

所使用的研究方法包括文献调研、理论分析、实验研究和案例分析。

通过对相关文献的查阅和总结,对两种算法进行概述和比较,进而提出改进思路。

在实验中,使用不同规模的数据集对两种算法进行测试,并比较其在时间和准确性方面的表现。

在案例分析中,将两种算法应用到不同的实际问题中,比较其实际应用的效果,并分析应用场景的特点。

预期结果:本文将研究旅行商问题的两种算法:遗传算法和模拟退火算法,并进行详细的分析和比较。

预计得出的结果包括:1.遗传算法和模拟退火算法的原理与流程。

2.两种算法的优缺点分析,以及针对缺点的改进措施。

3.两种算法在不同数据集上的性能比较,包括时间和准确性的分析。

4.将两种算法应用于不同问题的实例分析,包括应用场景的特点和优缺点分析。

总之,本研究将对探究两种算法在解决旅行商问题中的应用价值和优缺点,对如何选择合适的算法提供一定的参考和指导,以达到促进算法优化和实践应用的目的。

TSP问题遗传算法求解实验报告

TSP问题遗传算法求解实验报告

一、旅行商问题所谓旅行商问题(Travelling Salesman Problem , TSP),即最短路径问题,就是在给定的起始点S到终止点T的通路集合中,寻求距离最小的通路,这样的通路成为S点到T点的最短路径。

在寻找最短路径问题上,有时不仅要知道两个指定顶点间的最短路径,还需要知道某个顶点到其他任意顶点间的最短路径。

遗传算法方法的本质是处理复杂问题的一种鲁棒性强的启发性随机搜索算法,用遗传算法解决这类问题,没有太多的约束条件和有关解的限制,因而可以很快地求出任意两点间的最短路径以及一批次短路径。

假设平面上有n个点代表n个城市的位置, 寻找一条最短的闭合路径, 使得可以遍历每一个城市恰好一次。

这就是旅行商问题。

旅行商的路线可以看作是对n 个城市所设计的一个环形, 或者是对一列n个城市的排列。

由于对n个城市所有可能的遍历数目可达(n- 1)!个, 因此解决这个问题需要0(n!)的计算时间。

假设每个城市和其他任一城市之间都以欧氏距离直接相连。

也就是说, 城市间距可以满足三角不等式, 也就意味着任何两座城市之间的直接距离都小于两城市之间的间接距离。

二、遗传算法1 遗传算法介绍遗传算法是由美国J.Holland教授于1975年在他的专著《自然界和人工系统的适应性》中首先提出的,它是一类借鉴生物界自然选择和自然遗传机制的随机化搜索算法。

通过模拟自然选择和自然遗传过程中发生的繁殖、交叉和基因突变现象,在每次迭代中都保留一组候选解,并按某种指标从解群中选取较优的个体,利用遗传算子(选择、交叉和变异)对这些个体进行组合,产生新一代的候选解群,重复此过程,直到满足某种收敛指标为止。

遗传算法在本质上是一种不依赖具体问题的直接搜索方法,是一种求解问题的高效并行全局搜索方法。

其假设常描述为二进制位串,位串的含义依赖于具体应用。

搜索合适的假设从若干初始假设的群体集合开始。

当前种群成员通过模仿生物进化的方式来产生下一代群体,如随机变异和交叉。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《算法设计与课程设计》题目: TSP问题多种算法策略班级:计算机技术14学号:姓名:指导老师:完成日期:成绩:旅行商问题的求解方法摘要旅行商问题(TSP 问题)时是指旅行家要旅行n 个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。

该问题又称为货郎担问题、邮递员问题、售货员问题,是图问题中最广为人知的问题。

本文主要介绍用动态规划法、贪心法、回溯法和深度优先搜索策略求解TSP 问题,其中重点讨论动态规划法和贪心法,并给出相应求解程序。

关键字:旅行商问题;动态规划法;贪心法;回溯法;深度优先搜索策略 1引言旅行商问题(TSP)是组合优化问题中典型的NP-完全问题,是许多领域内复杂工程优化问题的抽象形式。

研究TSP 的求解方法对解决复杂工程优化问题具有重要的参考价值。

关于TSP 的完全有效的算法目前尚未找到,这促使人们长期以来不断地探索并积累了大量的算法。

归纳起来,目前主要算法可分成传统优化算法和现代优化算法。

在传统优化算法中又可分为:最优解算法和近似方法。

最优解算法虽然可以得到精确解,但计算时间无法忍受,因此就产生了各种近似方法,这些近似算法虽然可以较快地求得接近最优解的可行解,但其接近最优解的程度不能令人满意。

但限于所学知识和时间限制,本文重点只讨论传统优化算法中的动态规划法、贪心法、回溯法和深度优先搜索策略。

2正文2.1动态规划法2.1.1动态规划法的设计思想动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。

2.1.2 TSP 问题的动态规划函数假设从顶点i 出发,令'(,)d i V 表示从顶点i 出发经过'V 中各个顶点一次且仅一次,最后回到出发点i 的最短路径长度,开始时,{}'V V i =-,于是,TSP 问题的动态规划函数为:{}{}{}''(,)min (,)()(,)()ik ki d i V c d k V k k V d k c k i =+-∈=≠2.1.3算法分析(1)for (i=1; i<N; i++) //初始化第0列d[i][0]=c[i][0];(2)for (j=1; j< n-12 -1; j++)for (i=1; i<n; i++) //依次进行第i 次迭代if (子集V[j]中不包含i)对V[j]中的每个元素k ,计算V[m] == V[j]-k;d[i][j]=min(c[i][k]+d[k][m]);(3)对V[n-12 -1]中的每一个元素k ,计算V[m] == V[n-12-1]-k; d[0][ n-12 -1]=min(c[0][k]+d[k][m]);(4)输出最短路径长度d[0][ n-12 -1];2.1.4时间复杂性T()(2)n n O n =⨯动态规划法求解TSP 问题,把原来的时间复杂性是O(n!)的排列问题,转化为组合问题,从而降低了算法的时间复杂性,但它仍需要指数时间。

2.2贪心法2.2.1贪心法的设计思想贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。

换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。

这种局部最优选择并不总能获得整体最优解,但通常能获得近似最优解。

2.2.2最近邻点策略求解TSP 问题贪心法求解TSP 问题的贪心策略是显然的,至少有两种贪心策略是合理的:最近邻点策略和最短链接策略。

本文仅重点讨论最近邻点策略及其求解过程。

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

2.2.3算法分析1.P={ };2.V=V-{u0}; u=u0; //从顶点u0出发3.循环直到集合P 中包含n-1条边3.1查找与顶点u 邻接的最小代价边(u, v)并且v 属于集合V ;3.2 P=P+{(u, v)};3.3 V=V-{v};3.4 u=v; //从顶点v 出发继续求解2.2.4时间复杂性2T O n()但需注意,用最近邻点贪心策略求解TSP问题所得的结果不一定是最优解。

当图中顶点个数较多并且各边的代价值分布比较均匀时,最近邻点策略可以给出较好的近似解,不过,这个近似解以何种程度近似于最优解,却难以保证。

2.3回溯法2.3.1回溯法的设计思想回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。

但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

若已有满足约束条件的部分解,不妨设为(x1,x2,x3,……xi),I<n,则添加x(i+1)属于s(i+2),检查(x1,x2,……,xi,x(i+1))是否满足条件,满足了就继续添加x(i+2)、s(i+2),若所有的x(i+1)属于s(i+1)都不能得到部分解,就去掉xi,回溯到(xi,x2,……x(i- 1)),添加那些未考察过的x1属于s1,看其是否满足约束条件,为此反复进行,直至得到解或证明无解。

2.3.2 算法分析(回溯法+深度优先搜索策略)因为是采用回溯法来做,肯定是递归,然后还需要现场清理。

要设置一个二维数组来标识矩阵内容,然后回溯还需要设计一个二维标记数组来剪枝,设定一个目标变量,初始为无穷大,后续如果有比目标变量值小的就更新。

剪枝的条件就是如果走到当前节点的耗费值>=目标变量,就直接不再往下面走,向上走。

深度优先= 递归递归基:如果到达叶子节点的上一个节点,那么就进行是否更新的判断递归步:如果没有到达叶子节点,就进行剪枝操作,判断能否进入下一个节点,如果能,更新最优值2.3.3 关键实现(回溯法+深度优先搜索策略)1 //递归基:如果已经遍历到叶子节点的上一层节点,i标识递归深度if(i == g_n){//判断累加和是否超过最大值,如果有0,应该排除;满足这个条件,才打印if((g_iArr[pArr[i-1]][pArr[i]] != 0) && (g_iArr[pArr[g_n]][1] != 0) && (g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1] < g_iResult )){g_iResult = g_iCurResult + g_iArr[pArr[i-1]][pArr[i]] + g_iArr[pArr[g_n]][1];//用当前最优路径去更新最优路径,防止下一次没有for(int k = 1 ; k <= g_n ; k++){g_iBestPath[k] = pArr[k];2 //递归步:判断能否进入子树,需要尝试每一个节点else{//尝试不同的组合for(int j = i ; j <= g_n ; j++){//判断能否进入子树:如果当前值+下一个连线值的和< 最优值,就进入,0要passif( (g_iArr[pArr[i-1]][pArr[j]] != 0) && (g_iCurResult + g_iArr[ pArr[i-1] ][ pArr[j] ] < g_iResult) )3 //交换i与j,则i为当前可以尝试的范围//为完成后面k个元素的排列,逐一对数组第n-k~n个元素互换。

数组第一个元素为1,生成后面n-1个元素的排列//数组第一个元素与第二个元素互换,第一个元素为2,第2个元素为1,生成后面的n-1个元素的排列...swap(&pArr[i],&pArr[j]);//更新当前累加值,是i-1与i的g_iCurResult += g_iArr[ pArr[i-1] ][ pArr[i] ];//递归backTrace(i+1,pArr);//回溯,清空累加值;能够走到这里,说明上述结果不是最优解,需要向求解树上一层回退g_iCurResult -= g_iArr[pArr[i-1]][ pArr[i] ];swap(&pArr[i],&pArr[j]);*/2.3.4时间复杂性T = O(n!), 该方法并没有有效的提高时间效率。

3结论本文主要重点讨论了动态规划法、贪心法、回溯法和深度优先搜索策略求解TSP问题算法,并附录给出了相应程序,并通过对比得到动态规划法和贪心法相对更有优势,下面对这两种方法进行详述和进一步对比。

3.1动态规划法思想动态规划法中对于顶点元素生成的子集本文中用字符串形式存储,然后再用递归方法按照子集中元素个数从小到大开始赋值。

因为后面元素个数较多的子集与前面比其元素个数少1的子集间有一定对应关系,所以用递归方式,可以简便很多。

个人觉得这算本文的一大特色。

另,在计算d[i][j] =min(c[i][k]+d[k][j-1])时,获得d[k][j-1]的过程比较困难,运用字符串后,我们就可以首先找到指定字符,然后去掉该字符,返回剩余字符串,在与V[]逐个比较,找到与其相等的V[]中元素对应下标,此下标即为j-1;具体求解过程可参考附录源程序,有详细说明。

在求解最佳路径所经过城市顺序时,本文是通过边查找d[i][j]边记录路径的,这样可以省掉很多麻烦,另,路径也是采用字符串形式的数组,数组规模与存储城市间距离的c[][]数组相同,由于很多元素均不需赋值,这样做可能会浪费内存空间,但是目前还没找到更好地求解方法。

3.2贪心法思想贪心法中,由于贪心法相对动态规划法要简单很多,每次在查找最近城市时所得的顶点均为最后该法最佳路径所经过的城市编号,规模相对较小,容易确定,操作相对简单,所以本文用数组V[]存放最佳路径所经过的城市编号顺序相对来说方便很多。

另外,本文用path[]整型数组存放所经路径的长度,最后相加即可得最短路径。

3.3两者比较动态规划法相对贪心法来说虽然要精确些,但代码相对繁杂很多,对时间和空间要求很多,仅适用于城市数量较小的情况。

贪心法虽然比较简单,实现起来比较容易,但不是很精确,当图中顶点个数较多并且各边的代价值分布比较均匀时,贪心法可以给出较好的近似解,不过,这个近似解以何种程度近似于最优解,却难以保证。

相关文档
最新文档