分支限界法TSP问题

//分支限界法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
const int INF = 100000;
const int MAX_N = 22;
using namespace std;
//n*n的一个矩阵
int n;
int cost[MAX_N][MAX_N];//最少3个点,最多MAX_N个点
struct Node
{bool visited[MAX_N];//标记哪些点走了int s;//第一个点int s_p;//第一个点的邻接点int e;//最后一个点int e_p;//最后一个点的邻接点int k;//走过的点数int sumv;//经过路径的距离int lb;//目标函数的值(目标结果)bool operator <(const Node &p)const{return p.lb < lb;//目标函数值小的先出队列}
};
priority_queue<Node> pq;//创建一个优先队列
int low, up;//下界和上界
bool dfs_visited[MAX_N];//在dfs过程中搜索过//确定上界,利用dfs(属于贪心算法),贪心法的结果是一个大于实际值的估测结果
int dfs(int u, int k, int l)//当前节点,目标节点,已经消耗的路径
{if (k == n) return l + cost[u][1];//如果已经检查了n个节点,则直接返回路径消耗+第n个节点回归起点的消耗int minlen = INF, p;for (int i = 1; i <= n; i++){if (!dfs_visited[i] && minlen > cost[u][i])//取与所有点的连边中最小的边{minlen = cost[u][i];//找出对于每一个节点,其可达节点中最近的节点p = i;}}dfs_visited[p] = true;//以p为下一个节点继续搜索return dfs(p, k + 1, l + minlen);
}
void get_up()
{dfs_visited[1] = true;//以第一个点作为起点up = dfs(1, 1, 0);
}
//用这种简单粗暴的方法获取必定小于结果的一个值
void get_low()
{//取每行最小值之和作为下界low = 0;for (int i = 1; i <= n; i++){//创建一个等同于map的临时数组,可用memcpyint tmpA[MAX_N];for (int j = 1; j <= n; j++){tmpA[j] = cost[i][j];}sort(tmpA + 1, tmpA + 1 + n);//对临时的数组进行排序low += tmpA[1];}
}
int get_lb(Node p)
{int ret = p.sumv * 2;//路径上的点的距离的二倍int min1 = INF, min2 = INF;//起点和终点连出来的边for (int i = 1; i <= n; i++){//cout << p.visited[i] << endl;if (!p.visited[i] && min1 > cost[i][p.s]){min1 = cost[i][p.s];}//cout << min1 << endl;}ret += min1;for (int i = 1; i <= n; i++){if (!p.visited[i] && min2 > cost[p.e][i]){min2 = cost[p.e][i];}//cout << min2 << endl;}ret += min2;for (int i = 1; i <= n; i++){if (!p.visited[i]){min1 = min2 = INF;for (int j = 1; j <= n; j++){if (min1 > cost[i][j])min1 = cost[i][j];}for (int j = 1; j <= n; j++){if (min2 > cost[j][i])min2 = cost[j][i];}ret += min1 + min2;}}return (ret + 1) / 2;
}int solve()
{//贪心法确定上界get_up();//取每行最小的边之和作为下界//cout << up << endl;//testget_low();//cout << low << endl;//test//设置初始点,默认从1开始Node star;star.s = 1;//起点为1star.e = 1;//终点为1star.k = 1;//走过了1个点for (int i = 1; i <= n; i++){star.visited[i] = false;}star.visited[1] = true;star.sumv = 0;//经过的路径距离初始化star.lb = low;//让目标值先等于下界    int ret = INF;//ret为问题的解pq.push(star);//将起点加入队列while (pq.size()){Node tmp = pq.top();pq.pop();if (tmp.k == n - 1)//如果已经走过了n-1个点{//找最后一个没有走的点int p;for (int i = 1; i <= n; i++){if (!tmp.visited[i]){p = i;//让没有走的那个点为最后点能走的点break;}}int ans = tmp.sumv + cost[p][tmp.s] + cost[tmp.e][p];//已消耗+回到开始消耗+走到P的消耗//如果当前的路径和比所有的目标函数值都小则跳出if (ans <= tmp.lb){ret = min(ans, ret);break;}//否则继续求其他可能的路径和,并更新上界else{up = min(up, ans);//上界更新为更接近目标的ans值ret = min(ret, ans);continue;}}//当前点可以向下扩展的点入优先级队列Node next;for (int i = 1; i <= n; i++){if (!tmp.visited[i]){//cout << "test" << endl;next.s = tmp.s;//沿着tmp走到next,起点不变            next.sumv = tmp.sumv + cost[tmp.e][i];//更新路径和                next.e = i;//更新最后一个点                next.k = tmp.k + 1;//更新走过的顶点数                for (int j = 1; j <= n; j++) next.visited[j] = tmp.visited[j];//tmp经过的点也是next经过的点next.visited[i] = true;//自然也要更新当前点//cout << next.visited[i] << endl;next.lb = get_lb(next);//求目标函数//cout << next.lb << endl;if (next.lb > up) continue;//如果大于上界就不加入队列pq.push(next);//否则加入队列//cout << "test" << endl;}}//cout << pq.size() << endl;BUG:测试为0}return ret;
}
int main()
{cin >> n;for (int i = 1; i <= n; i++){for (int j = 1; j <= n; j++){cin >> cost[i][j];if (i == j){cost[i][j] = INF;}}}cout << solve() << endl;return 0;
}/*测试
5
100000 5 61 34 12
57 100000 43 20 7
39 42 100000 8 21
6 50 42 100000 8
41 26 10 35 100000
36
请按任意键继续. . .
*/

分支限界法TSP问题相关推荐

  1. 分支限界法 tsp java_基于分支限界法的旅行商问题(TSP)一

    //分支限界法 #include#include#include#include const int INF = 100000;const int MAX_N = 22;using namespace ...

  2. 算法设计与分析-TSP六种方法-贪心算法(最近邻点、最短链接)、蛮力法、动态规划法、回溯法、分支限界法、模拟退火

    旅行商问题,即TSP问题(Travelling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径, ...

  3. 分支限界法求解旅行商问题(TSP)

    1 实验内容 某售货员要到若干城市去推销商品,已知各城市之间的路程(以耗费矩阵的形式表示).要求使用分支限界算法,求得一条回路,该回路经过每个城市一次,且总的耗费(总距离)最小. 2 算法思路 分支限 ...

  4. 回溯法、分支限界法两种思想帮你轻松搞定旅行售货员问题(TSP)

    问题描述 某售货员要到若干城市去推销商品,已知各城市之间的路线(或旅费).要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(或总旅费)最小.本文只考虑4个城市的情况,下面这个带权 ...

  5. 最速下降法极小化rosenbrock函数 代码_典型算法思想与应用9|分支限界法与电路布线问题

    分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树. (1) 在分支限界法中,每一个活结点只有一次机会成为扩展结点.活结点一旦成为扩展结点,就一次性产生其所有儿子结点. (2) ...

  6. TSP问题-多种算法求解

    目录 前言 问题及思路 1.问题概述 2.设计思路 源码及测试 1.输入 2.代码 前言 算法大作业,综合应用8种算法解决TSP问题,分别是: 蛮力法(顺序查找) 分治法(快速排序) 贪心法(求上界) ...

  7. 分支限界法(算法分析与设计)

    0.概念 分支限界法常以广度优先(队列式(先进先出)分支限界)或以最小耗费(最大效益)优先的方式(优先队列分支限界)搜索问题的解空间树. 在分支限界法中,每一个活结点只有一次机会成为扩展结点.活结点一 ...

  8. 分支限界解决旅行商tsp问题

    本人的算法大作业 参考博客: http://blog.csdn.net/qq_32400847/article/details/51813606 http://www.cnblogs.com/ciel ...

  9. 回溯法和分支限界法解决旅行商问题

    实验三 旅行商问题 一. 实验内容 二.实验目的 三. 算法描述 1.回溯算法描述: 2.分支限界法算法描述: 四. 算法实现 1.数据结构及函数说明 (1) 回溯法求解TSP问题 (2) 分支界限求 ...

最新文章

  1. python将ElasticSearch索引数据读入pandas dataframe实战
  2. [Cocos2d-x For WP8]DrawPrimitives画图
  3. android r 编译找不到头文件_kOS(1):编译
  4. C#动态链接库的创建及使用
  5. leetcode159. 至多包含两个不同字符的最长子串
  6. 困计算机无法启动adb,win7系统无法启动adb.exe工具包的解决方法
  7. 前端多行文本溢出问题解决方案
  8. php编写九九乘法表
  9. 第三章_深度学习基础
  10. VC2012 正则替换
  11. 从数码宝贝看spring bean的生命周期
  12. tensorflow2.0莺尾花iris数据集分类|超详细
  13. [附源码]计算机毕业设计Python+uniapp基于安卓的校园跑腿代购476ww(程序+lw+APP+远程部署)
  14. 右键快捷创建mk文件
  15. vuex的基本应用(vuex的购物车案例)
  16. [Pytorch函数].repeat()
  17. 中国好SaaS走进海尔:企业关注重心从纯模式创新回归资源竞争
  18. 兔老大的系统设计(二)定时系统(延时队列)
  19. 计算机不显示苹果手机储存,电脑里手机在itunes里不显示
  20. Python输出时出现乱码“�밴���������. . . ”的解决方案

热门文章

  1. 学会使用perf性能分析工具--这一篇就够了
  2. 机器学习之最小二乘法
  3. 【C语言】输入字符串数组并排序
  4. 发布karaf的features
  5. CrowdHuman数据集
  6. 装机员U盘启动PE制作工具V5.0(UEFI+UD+自动安装MSDN版系统)
  7. html设置相对定位代码怎么写,Web前端面试题第八道—绝对定位与相对定位
  8. php停车场计时收费软件,ZPAY Time Billing Window(计时收费软件)
  9. 汇编语言学习:精华问题解答
  10. ios企业号的ID更改