穷举法、回溯法、分支界限法解决旅行商(TSP)问题

文章目录

  • 一、问题描述
  • 二、穷举法解决
    • 2.1 介绍
    • 2.2 代码
  • 三、回溯法解决
  • 四、分支界限法
    • 4.1 介绍
    • 4.2 代码


一、问题描述

 有一个旅行商由某城市出发,经过所有给定的 n n n 个城市后,再回到出发的城市。除了出发的城市外,其它城市只经过一回。这样的回路可能有多个,求其中路径成本最小的回路。

二、穷举法解决

2.1 介绍

 穷举法的本质是全排列。如下图对于四个点都连通的图,我们假定从 a a a 点出发,可以将获得 ( 4 − 1 ) ! (4-1)! (41)! 条路径。(公式为 ( n − 1 ) ! (n-1)! (n1)!

在这里插入图片描述

2.2 代码

#include <iostream>
using namespace std;//我们这里题目规模比较小 
int x[10]={0};         //城市编号数组,初值赋为0 
int bestx[10]={0};     //路线,初值赋为0 
int w = 0;             //过渡变量
int bestw = 1000;      //最优的费用void Tsp(int a[10][10], int n, int s)
{if (s == n){w = 0;//清零cout << "bestx: ";for (int i = 0; i < n; i++) {bestx[i] = x[i];cout << bestx[i] << " ";if (i < n - 1) {w += a[x[i]][x[i + 1]];}else {w += a[x[i]][x[0]];//回到起点的费用}}cout << "w:" << w << endl;if (bestw > w){bestw = w;//更新最优值}}else{for (int i = s; i < n; i++){//为什么要交换呢?因为要将x[s]作为起点进行往下搜索int t = x[i]; x[i] = x[s]; x[s] = t;Tsp(a, n, s + 1);t = x[i]; x[i] = x[s]; x[s] = t;}}
}int main()
{cout<<"请输入城市的个数: "<<endl; int n; //城市个数 cin>>n;for (int i = 0; i < n; i++){x[i] = i; //表示第i个城市编号,0到n-1}int a[10][10];  //a[i][j]表示从第i个城市到第j个的费用cout<<"请输入权值矩阵: "<<endl;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {cin >> a[i][j];}}Tsp(a, n, 1);//传1表示只搜从0开始的全排,传0表示所有全排cout << "最优的是:" << bestw << endl;return 0;
} 

在这里插入图片描述

三、回溯法解决

#include<iostream>
#include<algorithm>
#define MAX 10
using  namespace std;
int n;                   //城市个数
int a[MAX][MAX];         //城市间距离
int x[MAX];              //记录路径
int bestx[MAX]  = {0};   //记录最优路径
int bestp = 63355;       //最短路径长
int cp = 0;              //当前路径长
void backpack(int t){if(t>n){if((a[x[n]][1])&&(a[x[n]][1]+cp<bestp)){bestp = a[x[n]][1]+cp;for(int i = 1;i<=n;i++){bestx[i] = x[i];}}}else{for(int i = t;i<=n;i++){//约束为当前节点到下一节点的长度不为0,限界为走过的长度+当前要走的长度之和小于最优长度if((a[x[t-1]][x[i]])&&(cp+a[x[t-1]][x[i]]<bestp)){swap(x[t],x[i]);   cp+=a[x[t-1]][x[t]];backpack(t+1);cp-=a[x[t-1]][x[t]];swap(x[t],x[i]);}}}
}
int main(){cout<<"请输入城市的个数:"<<endl;cin>>n;      //顶点数for(int i = 1;i<=n;i++){x[i] = i;  //表示第i个城市编号 }cout<<"请输入权值矩阵:"<<endl;for(int i = 1;i<=n;i++){for(int j = 1;j<=n;j++){cin>>a[i][j];}}backpack(2);cout<<"最少旅行费用为:"<<bestp<<endl;cout<<"旅行路径为:"<<endl;for(int i = 1;i<=n;i++){cout<<bestx[i]<<" ";}cout<<bestx[1];return 0;
}

在这里插入图片描述

四、分支界限法

4.1 介绍

 分支限界法就是先将根结点放入活结点表中,然后循环取出表头结点,如果满足约束条件和限界条件就可以将当前结点的子结点(或者说下一级结点)放入活结点表中,直至得到所求解或者是活结点表为空为止。根据活结点表的存储方式可以将分支限界法分为队列式分支限界法和优先队列式分支限界法。这两种方法使用到的数据结构来是队列和堆,如有需要可以自己写,当然用直接用C++标准模板库中的queue和priority_queue会方便很多。

4.2 代码

#include <bits/stdc++.h>
#include <string>
#include <vector>
using namespace std;
#define MAXN 10int e[MAXN][MAXN];
int n, m, ans = 0x3f3f3f3f, vis[MAXN];
string anspath;void bfs(){queue<pair<string, int> > q;int dis = 0;vector<int> path;q.push({"1", 0});while(!q.empty()){string path = q.front().first;int dis = q.front().second;int pos = path[path.length()-1] - '0';if( path.length() == n ){dis += e[pos][1];if(dis < ans)   ans = dis, anspath = path + char(1 + '0');}else{for(int i = 1; i <= n; i ++ ){if(find(path.begin(), path.end(), (i + '0')) != path.end())    continue;if(dis + e[pos][i] > ans)   continue;q.push({path + char(i + '0'), dis + e[pos][i]});}}q.pop();}
}void show(){cout << ans << endl;for( int i = 0 ; i <= n ; i ++ )    cout << anspath[i] << (i == n ? "\n" : " ");
}int main(){cin >> n >> m;for( int i = 0 ; i < m ; i ++ ){int u, v, w;cin >> u >> v >> w;e[u][v] = e[v][u] = w;}bfs();cout << ans << endl;for( int i = 0 ; i <= n ; i ++ )    cout << anspath[i] << (i == n ? "\n" : " ");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/194351.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RepVgg: 网络结构重参化

CVPR2021 截至目前1004引 论文连接 代码连接 文章提出的问题 大多数的研究者追求的是设计一个好的网络结构,这种“好”体现在网络具有复杂的网络设计,这种网络虽然比简单的网络收获了更加高的准确率,但是网络结构中的大量并行分支,导致模型的难以应用和自定义,主要体现…

【神印王座】月夜大尺度诱惑,皓晨潜入月魔宫,枫秀降临男扮女装

Hello,小伙伴们&#xff0c;我是拾荒君。 为了能安全回到联盟&#xff0c;龙皓晨决定让月夜商队护送他们&#xff0c;这也是他们目前处境更快更安全回到人类境地的方法。于是&#xff0c;龙皓晨只身一人去寻找月夜&#xff0c;此次执行的任务完全超出龙皓晨的掌握之外&#xf…

Docker中快速安装RabbitMQ

文章目录 前言一、安装Docker二、安装RabbitMQ无脑命令行运行 总结 前言 在Ubuntu中的Docker容器中快速安装RabbitMQ&#xff0c;亲测有效&#xff0c;不废话&#xff0c;上操作。 一、安装Docker 直接按照Docker官方教程操作&#xff1a;官方安装教程 点进官网&#xff0c;往…

使用百度翻译API或腾讯翻译API做一个小翻译工具

前言 书到用时方恨少&#xff0c;只能临时抱佛脚。英文pdf看不懂&#xff0c;压根看不懂。正好有百度翻译API和腾讯翻译API&#xff0c;就利用两个API自己写一个简单的翻译工具&#xff0c;充分利用资源&#xff0c;用的也放心。 前期准备 关键肯定是两大厂的翻译API&#x…

【设计模式】创建型设计模式

创建型设计模式 文章目录 创建型设计模式一、概述二、单例模式三、工厂模式3.1 简单工厂模式&#xff08;静态工厂模式&#xff09;3.2 工厂方法模式3.3 抽象工厂模式3.3 工厂模式小结 四、原型模式五、建造者模式 一、概述 这些设计模式提供了一种在创建对象的同时隐藏创建逻…

【MySQL】insert和select单表查询详解(包含大量示例,看了必会)

insert和select 前言正式开始Create全列插入指定列插入多行插入插入失败就更新替换 Retrieveselect语法简介开始查询全列查询指定列查询select后面跟表达式对结果去重条件查询 查询的示例英语不及格的同学及英语成绩 ( < 60 )语文成绩在 [80, 90] 分的同学及语文成绩数学成绩…

spass-二元变量相关分析

基础概念 计算相关系数r&#xff1a;利用样本数据计算样本相关系数&#xff0c;样本相关系数反映了两变量间线性相关程度的强弱。相关系数的取值范围界于-1与1之间&#xff0c;即-1≤r≤1 当0<r ≤ 1&#xff0c;表明变量之间存在正相关关系&#xff1b; 当-1 ≤ r…

4、FFmpeg命令行操作10

音视频处理流程 先看两条命令 ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x720 test_1280x720.flv ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx265 -s 1280x720 test_1280x720.mkv ffmpeg音视频处理流程

网络协议入门 笔记一

一、服务器和客户端及java的概念 JVM (Java Virtual Machine) : Java虚拟机&#xff0c;Java的跨平台:一次编译&#xff0c;到处运行&#xff0c;编译生成跟平台无关的字节码文件 (class文件)&#xff0c;由对应平台的JVM解析字节码为机器指令 (010101)。 如下图所示&#xff0…

《Fine-Grained Image Analysis with Deep Learning: A Survey》阅读笔记

论文标题 《Fine-Grained Image Analysis with Deep Learning: A Survey》 作者 魏秀参&#xff0c;南京理工大学 初读 摘要 与上篇综述相同&#xff1a; 细粒度图像分析&#xff08;FGIA&#xff09;的任务是分析从属类别的视觉对象。 细粒度性质引起的类间小变化和类内…

springboot集成nacos并实现自动刷新

目录 1.说明 2.示例 3.自动刷新的注意点 1.说明 springboot项目中存在好多配置文件&#xff0c;比如配置数据信息&#xff0c;redis信息等等&#xff0c;配置文件可以直接放在代码&#xff0c;也可以放在像nacos这样的组件中&#xff0c;实现动态的管理&#xff0c;修改配置…