c++旅行商问题 (暴力解)

news2024/12/22 14:39:30

目录

  • 一、旅行商问题简介
    • 旅行商问题
    • 问题概述
    • 问题由来
  • 二、枚举所有方案
    • 1、思路
    • 2、代码
    • 3、复杂度分析
  • 三、深度优先搜索
    • 1、思路
    • 2、代码
    • 3、复杂度分析

一、旅行商问题简介

旅行商问题

  TSP,即旅行商问题,又称TSP问题(Traveling Salesman
Problem),是数学领域中著名问题之一。

问题概述

  假设有一个旅行商人要拜访N个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。TSP问题是一个NPC问题。

问题由来

  TSP的历史很久,最早的描述是1759年欧拉研究的骑士周游问题,即对于国际象棋棋盘中的64个方格,走访64个方格一次且仅一次,并且最终返回到起始点。

  TSP由美国RAND公司于1948年引入,该公司的声誉以及线形规划这一新方法的出现使得TSP成为一个知名且流行的问题。

示例:
在这里插入图片描述

黑色数字代表点、红色代表路径的花费

输入:

4 6
1 2 1
1 4 2
1 3 4
2 3 1
2 4 2
3 4 3

输出:

最短距离为:72条最短路径:
1-->4-->3-->2-->1
1-->2-->3-->4-->1

提示:

第一行输入点的个数n和边的个数m,点的编号为1~n
接下来m行输入m条边以及花费,x y v,表示点x和点y之间有一条无向边,边的花费为v

二、枚举所有方案

1、思路

  我们只需要固定起点和终点,用全排列枚举中间点的排列,判断方案是否是最优的,如果是,则记录下来
  例如4个点,那么我们固定起点为0,终点为0,枚举1-3的全排列,判断每一种方案是否是最优的,选择性第保留或者抛弃
  4个点的方案有6个:
  0 1 2 3 0
  0 1 3 2 0
  0 2 1 3 0
  0 2 3 1 0
  0 3 1 2 0
  0 3 2 1 0

2、代码

#include<bits/stdc++.h>
using namespace std;
int n,m;//n点的个数,m边的个数 
int a[15][15];//邻接矩阵存无向图 
int p[15];
long long ans=0x3f3f3f3f;
vector<vector<int> > paths;

void init(){//初始化 
	memset(a,0x3f,sizeof a);//初始化为一个足够大的值,代表不可达 
	for(int i=0;i<15;i++){
		p[i]=i;
	}
	cout<<"请输入点和边的个数:"<<endl;
	cin>>n>>m;
	p[0]=0;//起点为0 
	p[n]=0;//终点为0 
	cout<<"请输入"<<m<<"条边:"<<endl;
	for(int i=0;i<m;i++){
		int x,y,val; 
		cin>>x>>y>>val;
		x--;
		y--;
		a[x][y]=val;
		a[y][x]=val;
	}
} 


long long check(){
	long long sum=0;
	for(int i=1;i<=n;i++){
		if(a[p[i-1]][p[i]]==0x3f3f3f3f){//如果该点不可达,那么就直接退出 
			return 0x3f3f3f3f;
		}
		sum+=a[p[i-1]][p[i]];
	}
	return sum;
}


void print(){//打印路径 
	cout<<"最短距离为:"<<ans<<endl;
	cout<<"共"<<paths.size()<<"条最短路径:" <<endl; 
	for(int i=0;i<paths.size();i++){
		for(int j=paths[i].size()-1;j>=0;j--){
			if(j<paths[i].size()-1){
				cout<<"-->";
			}
			cout<<paths[i][j]+1;
		}
		cout<<endl;
	}
}


int main(){
	init();
	do{
		long long sum=check();
		if(sum<=ans){
			if(sum<ans){//如果有更优的解,那么就抛弃掉先去的路径 
				paths.clear();
			}
			ans=sum;
			vector<int> path;
			for(int i=0;i<=n;i++){
				path.push_back(p[i]);
			}
			paths.push_back(path);//添加当前的路径 
		}
	}while(next_permutation(p+1,p+n));//枚举1~n-1的全排列 
	
	if(ans==0x3f3f3f3f){
		cout<<"该图无解"<<endl;
		return 0; 
	}
	print();
}

3、复杂度分析

  时间复杂度: 枚举全排列,对每一个排列做一次查询,时间复杂度为O(n*(n!))
  空间复杂度: 存储所有的最优的路径,空间复杂度为O(n*(n!))

三、深度优先搜索

1、思路

  我们从0点出发,深度优先搜索所有的路径,符合要求则记录下来

2、代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[15][15];//邻接矩阵存无向图 
long long ans=0x3f3f3f3f;//存储答案
vector<vector<int> > paths;//存储路径 

void init(){//初始化 
	memset(a,0x3f,sizeof a);//初始化为一个足够大的值,代表不可达 
	cout<<"请输入点和边的个数:"<<endl;
	cin>>n>>m;
	cout<<"请输入"<<m<<"条边:"<<endl;
	for(int i=0;i<m;i++){
		int x,y,val; 
		cin>>x>>y>>val;
		x--;
		y--;
		a[x][y]=val;
		a[y][x]=val;
	}
} 

long long sum=0;
vector<int> path(1,0);//存储实时的路径 
int vis[15];//判断该点是否已经走过了 
void dfs(int i){//i指的是目前在哪个点 
	if(i==0){//目前的点是终点
		int flag=1;
		for(int j=0;j<n;j++){//并且所有的点都走过一遍
			if(vis[j]==0)flag=0;
		}
		if(flag==1){
			if(sum<=ans){
				if(sum<ans){//如果有更优的解,则抛弃之前存储的路径 
					paths.clear();
				}
				ans=sum;
				paths.push_back(path);//存储当前路径 
			}
			return;
		}
	}
	for(int j=0;j<n;j++){//深搜+回溯 
		if(vis[j]==0){
			path.push_back(j); 
			sum+=a[i][j];
			vis[j]=1;
			dfs(j);
			path.pop_back();
			sum-=a[i][j];
			vis[j]=0;
		}
	} 
	
}

void print(){//打印路径 
	cout<<"最短距离为:"<<ans<<endl;
	cout<<"共"<<paths.size()<<"条最短路径:" <<endl; 
	for(int i=0;i<paths.size();i++){
		for(int j=paths[i].size()-1;j>=0;j--){
			if(j<paths[i].size()-1){
				cout<<"-->";
			}
			cout<<paths[i][j]+1;
		}
		cout<<endl;
	}
}

int main(){
	init();
	dfs(0);
	if(ans==0x3f3f3f3f){
		cout<<"该图无解"<<endl;
		return 0; 
	}
	print();
}

3、复杂度分析

  时间复杂度: 深度搜索O(n!),每次都要判断是否符合题意O(n),总时间复杂度为O(n*(n!))
  空间复杂度: 存储所有的最优的路径,空间复杂度为O(n*(n!))

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

白盒测试与黑盒测试

白盒测试技术 白盒测试技术也称结构性测试&#xff0c;是一种设计测试用例的方法&#xff0c;一般用于分析程序的内部结构&#xff0c;使用该方法测试程序时测试者可以看到被测试程序&#xff0c;并分析其内部结构。 按照被测试测试时是否需要执行测试程序可以分为静态和动态…

RK3399平台开发系列讲解(中断篇)中断控制器驱动初始化

🚀返回专栏总目录 文章目录 一、设备树源文件1.1、gic控制器节点1.2、timer节点二、中断控制器匹配表三、中断控制器初始化3.1、函数of_irq_init3.2、函数gicv3_of_init3.3、函数gic_init_bases沉淀、分享、成长,让自己和他人都能有所收获!😄 一、设备树源文件 ARM64架构…

web前端网页制作课作业:甜甜圈蛋糕店(HTML+CSS+JavaScript)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

用DIV+CSS技术设计的水果介绍网站(web前端网页制作课作业)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

NodeJs实战-Express构建照片存储网站(2)-上传、展示文件

Express构建照片存储网站2-上传、展示文件静态资源显示图片photo页面展示文件夹下的图片上传文件增加上传页面的路由增加提交接口的路由网站效果图项目地址上一节使用的静态数据存储的图片的数据&#xff0c;本节增加如下功能 1–上传文件 2–展示文件 静态资源显示图片 app.…

企业微信自建应用手动授权,获取用户详细信息

开始开发 最后更新&#xff1a;2022/10/11 企业微信提供了OAuth的授权登录方式&#xff0c;可以让从企业微信终端打开的网页获取成员的身份信息&#xff0c;从而免去登录的环节。 企业应用中的URL链接&#xff08;包括自定义菜单或者消息中的链接&#xff09;&#xff0c;均可…

宇视高空抛物相机配置指导

宇视高空抛物相机配置指导 登录摄像机网页界面&#xff0c;进入[配置>智能监控>智能功能]页面启用<高空抛物>功能&#xff0c;并进入高空抛物配置界面&#xff1b; 添加/删除检测规则&#xff0c;根据实际高空抛物场景和规则下发要求绘制检测区域&#xff1b; (…

必看!!!客户端requests与服务端request收发请求

当使用代码进行接口访问的时候&#xff0c;请求的发送与请求的接受使用的参数应该怎么如何传输能够请求到正确的响应呢? 一、使用GET请求发送&#xff0c;客户端与服务端的参数传输与接受。 1、服务端&#xff0c;首先使用web框架写一个简单的接口&#xff0c;接收两个参数&…

FineReport常用配置和方法

目录 1、隐藏参数面板的小箭头&#xff1a; 1、隐藏参数面板的小箭头&#xff1a; 查看小箭头的class&#xff0c;css设置如下属性&#xff1a; 隐藏按钮&#xff1a; // 旧版 $(.parameter-container-collapseimg-up).hide(); // 新版 $(.report-main-parameter-container-…

浙大MBA考研经验分享:名校梦不可负~

上大学的时候考研失败&#xff0c;对于没能进入浙大求学一直是我心里的遗憾&#xff01;但是毕业以来至今工作三年&#xff0c;职场上的经历让我意识到持续学习提升的重要性。一边工作一边备考&#xff0c;对于基础普通的我来说&#xff0c;一年备战能够以211分的成绩成功上岸浙…

Collection体系集合

一、Collection体系结构 Collection体系结构的根接口&#xff0c;代表一组对象&#xff0c;称为“集合”。 List接口的特点&#xff1a;有序、有下标、元素可重复。 Set 接口的特点&#xff1a;无序、无下标、元素不能重复。 二、Collection父接口 特点&#xff1a;代表一组…

分布式计算模型Mapreduce实践与原理剖析(一)

第一章 MapReduce核心理论 1.1 什么是MapReduce MapReduce 是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于 Hadoop 的数据应用” 的核心框架 。 MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并行运…

[短的文章] Spring Boot 日志创建使用、日志级别、@Slf4j、日志持久化——Spring Boot 系列

前言&#xff1a; 想必日志大家伙在项目开发调试过程中常会使用&#xff0c;这篇文章我们来一起探讨一下 Spring Boot 项目中日志的定义与使用&#xff0c;主要针对以下几个方面重点叙述 日志级别 日志框架进行日志定义 日志持久化 1 日志简述 1.1 为什么使用日志 日志大家在…

机器学习-逻辑回归

机器学习-基础知识 机器学习-线性回归 机器学习-逻辑回归 机器学习-聚类算法 机器学习-决策树算法 机器学习-集成算法 机器学习-SVM算法 文章目录逻辑回归1. 线性逻辑回归1.1. 理论基础1.2. 逻辑回归模拟步骤1.2.1. 数据集1.2.2. 模拟逻辑回归类模块1.2.3. 测试模块1.2.4. 数据…

PN532开发指南(uart)

开发环境 STM32F103C8T6 STM32f103c8t6最小系统板&#xff08;typec接口&#xff09; STM32CUBEMX PN532模块 一、NFC简介 NFC(Near Field Communication)近场通信&#xff0c;是一种短距高频的无线电技术&#xff0c;在13.56MHz频率运行于20厘米距离内。其传输速度有106Kb…

懒人福利:只需一行代码,导入所有的 Python 库

前言 今天给大家介绍一个懒人 Python 库—— Pyforest 。 使用一行代码&#xff0c;就能导入所有的 Python 库(本地已经安装的)。 GitHub 地址 https://github.com/8080labs/pyforest &#xff08;文末送读者福利&#xff09; / 01 / 介绍 Python 因为有着成千上万个功能…

paper 阅读: An introduction to ROC analysis

发布于2005年&#xff0c;附论文链接如下&#xff1a; https://ccrma.stanford.edu/workshops/mir2009/references/ROCintro.pdf 之前一直都是从各种博客上了解ROC的&#xff0c;最近才看到这一篇paper。 写在前面 用 True&#xff08;T&#xff09;和 False&#xff08;F&…

BGP进阶:BGP 基础实验配置

实验拓扑 实验需求 R1、R2、R3属于AS123&#xff0c;R4属于AS 400&#xff1b;AS123内的R1、R2、R3运行OSPF&#xff0c;通告各自直连接口&#xff0c;注意OSPF域的工作范围&#xff1b;R3-R4之间建立eBGP邻居关系&#xff0c;R2暂时不运行BGP&#xff0c;R1-R3之间建立iBGP邻…

MCE | D-萤光素 Protocol 在手,生物发光检测无忧!

■ Q: D-萤光素的作用原理 D-萤光素 (D-Luciferin) 是萤火虫萤光素酶 (Firefly Luciferase) 的化学发光底物。在ATP 和萤光素酶存在下&#xff0c;萤光素能够被氧化发光 (图 1)。当萤光素过量时&#xff0c;发光亮度与萤光素酶浓度呈正相关。通过萤光素/萤光素酶生物发光体系&…

小程序容器技术加快推动国产操作系统“上车”

计算机是当前乃至未来的基础工具&#xff0c;而负责管理计算机硬件与软件资源、提供必须的人机交互机制的操作系统无疑是整个计算机的核心系统软件。 可以说&#xff0c;操作系统是当前一个国家提升综合实力过程中必须要攻克、掌握的核心技术之一。 国产操作系统多为以Linux为…