分支限界解决旅行商tsp问题
本人的算法大作业
参考博客:
http://blog.csdn.net/qq_32400847/article/details/51813606
http://www.cnblogs.com/cielosun/p/5654582.html
http://www.cnblogs.com/cielosun/p/5654582.html
基本思想
1.按宽度优先策略遍历解空间树
2.在遍历过程中,对处理的每个结点vi,根据界限函数,估计沿该结点向下搜索所可能达到的完全解的目标函数的可能取值范围—界限bound(vi)=[downi, upi]
3.从中选择使目标函数取的极值(最大、最小)的结点优先进行宽度优先搜索,从而不断调整搜索方向,尽快找到问题解。
各结点的界限函数bound(vi)=[downi, upi]是解决问题的关键,通常依据具体问题而定。常见的两种分支限界法是队列式分支限界法和优先队列式分支限界法,它们分别按照队列先进先出的原则和优先队列中规定的优先级选取下一个节点为扩展节点。分支限界法与回溯法的不同之处在于求解目标和搜索方式的不同。回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解;回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。我们以TSP问题为例用分支限界法解决。TSP问题(Traveling Salesman Problem)是数学领域中著名问题之一。假设有一个旅行商人要拜访N个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市,要求路径的总和最小。考虑下图所示的情况及其代价矩阵,假定起始城市为1号城市。
算法描述
输入:城市数量n和城市之间路程的代价矩阵
输出:城市之间固定起点的哈密顿回路的最短路程
1)计算初始上下界,使用暴力排序对代价矩阵进行排序计算出下界,使用贪心算法计算出上界。
2)定义一个类保存开始节点、结束节点、已遍历的城市及其数量、已遍历的路径长度、当前节点的目标函数值,类中定义一个方法计算当前节点的目标函数值,由当前已遍历的路径的二倍加上进出其余未遍历城市的最短路径,再加上出当前城市的最短路径和进起始城市的最短路径,取其二分之一,是当前节点的目标函数值,即当前节点的下界。
3)把起始节点加入优先队列,当优先队列不为空时,取出当前优先级最高的节点,若当前已遍历n-1个城市,则计算当前路径长度加上最后一个节点的路径长度和记为ans,若ans小于所有目标函数值,则跳出循环并把ans作为最优解输出。若ans不小于所有目标函数值,则更新上界和可行解继续循环。若当前已遍历城市个数小于n-1,则判断当前取出节点的子节点的目标函数是否小于上界,若小于则添加进优先队列,否则继续判断下一个子节点。
样例矩阵
搜索树
结果:
代码:
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<queue>#define INF 100000
#define MAX 100
using namespace std;int result;
int weight[MAX][MAX];class City{
public:City(){ }int m_iUpWeight; //上界 int m_iDownWeight; //下界 int m_iCount; //输入的总的城市数量 int visitedCitys[MAX]; //已走过的城市
};
City city;class Nodes{
public:int visitedCity[MAX]; //已走过的城市 int numbers; //已走过的城市数量 int endCity; //已走过的最后一个城市 int startCity; //已走过的第一个城市 int sumLength; //已走过的长度 int aimFun; //当前节点的目标函数值 Nodes(){for(int i=0;i<MAX;++i){visitedCity[i]=0;}visitedCity[0]=1;numbers=1;endCity=0;startCity=0;sumLength=0;aimFun=0;}bool operator <(const Nodes &p )const { return aimFun>p.aimFun; } int calAimFun(){int ret=sumLength*2;int min1=INF,min2=INF;for(int i=0;i<city.m_iCount;++i){if(visitedCity[i]==0 && min1>weight[i][startCity]){min1=weight[i][startCity];}}for(int i=0;i<city.m_iCount;++i){if(visitedCity[i]==0 && min2>weight[endCity][i]){min2=weight[endCity][i];}}ret+=(min1+min2);for(int i=0;i<city.m_iCount;++i){if(visitedCity[i]==0){min1=INF;min2=INF;for(int j=0;j<city.m_iCount;++j){if(min1>weight[i][j]){min1=weight[i][j];}}for(int j=0;j<city.m_iCount;++j){if(min2>weight[j][i]){min2=weight[j][i];}}ret+=(min1+min2); }}return ret%2==0?ret/2:(ret/2+1);}
}; //优先队列,比较大小然后输出最先的值
priority_queue<Nodes> q;void input(){scanf("%d",&city.m_iCount);for(int i=0;i<city.m_iCount;++i){for(int j=0;j<city.m_iCount;++j){if(i==j)weight[i][j]=INF;else cin>>weight[i][j];}}
}//确定下界
int getDownWeight(){int downWeight=0;int temp[city.m_iCount];for(int i=0;i<city.m_iCount;++i){memcpy(temp,weight[i],sizeof(temp));sort(temp,temp+city.m_iCount);downWeight+=(temp[0]+temp[1])/2;} return downWeight;
}
//贪心法确定上界
int dfs(int now_p,int count,int sumLength){if(count==city.m_iCount-1){return sumLength+weight[now_p][0];}int min=INF;int next_p=-1;for(int i=0;i<city.m_iCount;++i){if(city.visitedCitys[i]==0&&min>weight[now_p][i]){min=weight[now_p][i];next_p=i;} }city.visitedCitys[next_p]=1;return dfs(next_p,count+1,sumLength+min);
}int getUpWeight(){memset(city.visitedCitys,0,sizeof(city.visitedCitys)); //标记已走过的城市 city.visitedCitys[0]=1;return dfs(0,0,0);
}int solve(){city.m_iUpWeight=getUpWeight();city.m_iDownWeight=getDownWeight();Nodes node;node.aimFun=city.m_iDownWeight;int ret=INF;q.push(node);while(!q.empty()){Nodes temp=q.top();
//cout<<"拿出:"<<temp.endCity<<endl; q.pop();if(temp.numbers==city.m_iCount-1){int p=-1;for(int i=0;i<city.m_iCount;++i){if(0==temp.visitedCity[i]){p=i;break;}}int ans=temp.sumLength+weight[temp.endCity][p]+weight[p][temp.startCity];Nodes judge=q.top();if(ans<=judge.aimFun){ret=min(ans,ret);break;}else{city.m_iUpWeight=min(city.m_iUpWeight,ans);ret=min(ret,ans);continue; }}Nodes next;for(int i=0;i<city.m_iCount;++i){if(temp.visitedCity[i]==0){next.endCity=i;next.startCity=temp.startCity;next.numbers=temp.numbers+1;next.sumLength=temp.sumLength+weight[temp.endCity][i];for(int k=0;k<city.m_iCount;++k)next.visitedCity[k]=temp.visitedCity[k];next.visitedCity[i]=1;next.aimFun=next.calAimFun();//cout<<next.endCity<<" 的目标函数是 "<<next.aimFun<<endl;if(next.aimFun>=city.m_iUpWeight)continue;q.push(next);
//cout<<next.endCity<<" 添加"<<endl;}}}return ret;
} int main(){memset(weight,0,sizeof(weight));input();city.m_iDownWeight=getDownWeight();city.m_iUpWeight=getUpWeight();//cout<<"city.m_iDownWeight "<<city.m_iDownWeight<< "city.m_iUpWeight "<<city.m_iUpWeight<<endl; int ret=solve();//cout<<"最优解为:"<<endl;cout<<ret<<endl;return 0;
}
分支限界解决旅行商tsp问题相关推荐
- 模拟退火(SA, Simulated Annealing)算法解决旅行商TSP问题
01 什么是旅行商问题(TSP)? TSP问题(Traveling Salesman Problem,旅行商问题),由威廉哈密顿爵士和英国数学家克克曼T.P.Kirkman于19世纪初提出.问题描述如 ...
- 【Tsinghua】旅行商(TSP)
关于这道题,我要说两句,这道题我觉得我用拓扑排序的思路肯定是没错的,而且也对了几组数据,但是其他几组却超时,肯定是哪里的代码优化的不够好...... 最后只得了40分... 旅行商(TSP) 描述 S ...
- 鲸鱼优化算法WOA求解旅行商TSP优化问题(2022.6.2)
鲸鱼优化算法WOA求解旅行商TSP优化问题(2022.6.2) 引言 1.鲸鱼优化算法WOA 1.1 WOA算法原理介绍 1.1.1 包围猎物 1.1.2 气泡网式攻击猎物(开发阶段) 1.1.3 寻 ...
- 【路径规划】基于灰狼算法求解旅行商TSP问题matlab源码
一.旅行商问题 TSP问题即旅行商问题,经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地.应如何选择行进路线,以使总的行程最短.从图 ...
- Solve TSP with dynamic programming——动态规划解决旅行商(邮递员)问题
无向简单图的TSP算法 小规模精确解: 算法思想: 小规模精确解的算法中心思想是动态规划思想. 假设给定顶点集合V为{0,1,2,3,4,... .n}.由于图为无向完全图,我们可以很自然地将0视为输 ...
- 遗传算法解决旅行商(TSP)问题
遗传算法解决旅行商问题 作为NP难的经典问题,旅行商问题有多种算法可以解决. 我学习的过程中,首先看到了模拟退火算法解决旅行商问题的过程,模拟退火算法可以保证100%的找到全局最小值. 在我研究遗传算 ...
- MATLAB实战系列(十九)-遗传算法解决TSP(旅行商)问题-应用及解析(文末附MATLAB源码)
接上篇MATLAB实战系列(十八)-遗传算法解决TSP(旅行商)问题-算法原理 https://wenyusuran.blog.csdn.net/article/details/114060030 感 ...
- matlab算法大全 pdf_遗传模拟退火算法求解旅行商(TSP)问题
hello大家好,很高兴又和大家见面了.在之前的遗传算法(GA)求解旅行商问题(TSP)MATLAB代码讲解和模拟退火(SA)算法求解旅行商 (TSP)问题MATLAB代码讲解这两篇推文中,分别讲解了 ...
- 蚁群算法--旅行商(TSP)问题详解
蚁群算法--旅行商(TSP)问题详解 蚁群算法 问题与分析 结果显示与分析 蚁群算法 蚁群算法(ant colony optimization)最早是由Marco Dorigo等人在1991年提出,他 ...
最新文章
- 大战设计模式【23】—— 原型模式
- javascript中的constructor
- 设置一段文字显示不同的颜色及大小等属性
- ios kvo 要引入_iOS KVO 实现原理 和 自己实现KVO
- 苹果手机mov文件如何复制到电脑_如何在手机上访问电脑上的文件(超详细步骤) iPhone版...
- php文件便利,PHP便利文件夹下所有文件,创建压缩包
- 【jQuery学习】—jQuery操作CSS和表格
- 从苹果 M1 到英伟达 Grace,“缝合风”为何在芯片大厂中盛行?
- mysql 常用管理命令
- hypersion oracle_Oracle Hyperion财务管理之合并报表
- 实现虚拟机VMware上Centos操作系统与主机windows之间互相复制与粘贴
- 微信h5界面隐藏刷新功能_隐藏微信H5页面下拉出现的网址
- 准备给ubuntu18.04安装杀毒软件
- c#拼图碎片形状_1-3拼图碎片
- 利用Photoshop进行快速切图
- overflow:auto
- CAD中用lisp程序实现批量偏移_求一个cad lisp 双向偏移的代码
- uC/OS iii(三)任务管理之任务状态
- (C++)将数据库文件导出XML文件以及解析XML文件生成数据库文件的处理方法
- java计算机毕业设计网络课程考试源代码+数据库+系统+lw文档