Traveling Salesman among Aerial Cities 旅行商(TSP)问题
题目链接:点我
问题:
给你n个点的坐标(x,y,z)。从点(a,b,c) 到另一个点 (p,q,r) 的距离是:|p−a|+|q−b|+max(0,r−c)
问你从一个点为起点,找一条能经过其他所有点的路径,最后回到起点(除了起点可以经过两次,其他所有点只能经过一次
问你这个环的长度最小是多少
问题求解:
假设从顶点s出发,令d(i, V)表示从顶点i出发经过V(是一个点的集合)中各个顶点一次且仅一次,最后回到出发点s的最短路径长度。
我们使用dist(i,j)表示从i点到j点的距离
1、当V是空集的时候,d(i,V)就表示直接从i点回到了s点,也就是dist(i,s)
2、当V不是空集的时候,那么就是对子问题的最优求解。你必须在V这个城市集合中,尝试每一个,并求出最优解。
d(i,V)=min(d(k,V-{k})+dist(i,k)) (V-{k}表示在V集合中把k点去掉
这也就是dp方程了
复杂度:
2n*n2
代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define min(a,b) ((a>b)?b:a)
using namespace std;
typedef long long ll;
const int maxn = 25 + 10;
const long long ll_INF=0x3f3f3f3f3f3f3f3fLL;
const long long INF=0x3f3f3f3f;
int n,w[maxn][maxn],dp[maxn][1<<20],m;
vector<int>path;
//dp[i][j]保存顶点i到状态j最后回到起始点的最小距离
struct Point
{
int x,y,z;
} point[maxn];
int dist(int i,int j)
{
return abs(point[i].x-point[j].x)+abs(point[i].y-point[j].y)+max(0,point[j].z-point[i].z);
}
void TSP()
{
//我们把起点看作0号节点
for(int i=0; i<n; ++i)
{
//初始化dp数组
dp[i][0]=w[i][0];
}
//按照dp方程求解
for(int j=1; j<m; ++j) //状态
{
for(int i=0; i<n; ++i)
{
dp[i][j]=INF;
if( ((j >> (i-1)) & 1) == 1) //这样判断而不是j>>i这样判断,是因为可以直接得到答案就在dp[n][m-1]
{
//要不然对于dp[n][m-1]的状态肯定每一位都是1,如果换成上面那个判断,那么这个状态的值就是
continue; //INF(因为continue掉了
}
for(int k=1; k<n; ++k)
{
if( ((j >> (k-1)) & 1) == 0)
{
continue;
}
if( dp[i][j] > w[i][k] + dp[k][j^(1<<(k-1))])
{
dp[i][j] = w[i][k] + dp[k][j^(1<<(k-1))];
}
}
}
}
}
//判断结点是否都以访问,不包括0号结点
bool isVisited(bool visited[])
{
for(int i = 1 ; i<n ; i++)
{
if(visited[i] == false)
{
return false;
}
}
return true;
}
//获取最优路径,保存在path中,根据动态规划公式反向找出最短路径结点
void getPath()
{
//标记访问数组
bool visited[n] = {false};
//前驱节点编号
int pioneer = 0,minn = INF, S = m - 1,temp ;
//把起点结点编号加入容器
path.push_back(0); while(!isVisited(visited))
{
for(int i=1; i<n; i++)
{
if(visited[i] == false && (S&(1<<(i-1))) != 0)
{
if(minn > w[i][pioneer] + dp[i][(S^(1<<(i-1)))])
{
minn = w[i][pioneer] + dp[i][(S^(1<<(i-1)))] ;
temp = i;
}
}
}
pioneer = temp;
path.push_back(pioneer);
visited[pioneer] = true;
S = S ^ (1<<(pioneer - 1));
minn = INF;
}
}
//输出路径
void printPath()
{
cout<<"最小路径为:";
vector<int>::iterator it = path.begin();
for(it ; it != path.end(); it++)
{
cout<<*it<<"--->";
}
//单独输出起点编号
cout<<0;
}
int main()
{
//printf("%d\n",(3>>(-1))); 6
scanf("%d",&n);
m=(1<<(n-1));
for(int i=0; i<n; ++i)
{
scanf("%d%d%d",&point[i].x,&point[i].y,&point[i].z);
}
for(int i=0; i<n; ++i)
{
for(int j=0; j<n; ++j)
{
if(i==j) w[i][j]=0;
else
w[i][j]=dist(i,j);
}
}
TSP();
printf("%d\n",dp[0][m-1]);
//下面用于输出路径
// getPath();
// printPath();
return 0;
}
Traveling Salesman among Aerial Cities 旅行商(TSP)问题的更多相关文章
- 遗传算法的简单应用-巡回旅行商(TSP)问题的求解
上篇我们用遗传算法求解了方程,其中用到的编码方式是二进制的编码,实现起来相对简单很多, 就连交配和变异等操作也是比较简单,但是对于TSP问题,就稍微复杂一点,需要有一定的策略, 才能较好的实现. 这次 ...
- 二进制状态压缩dp(旅行商TSP)POJ3311
http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS Memory Limit: 65536K Total Subm ...
- Hamilton回路 旅行商TSP问题 /// dp oj1964
题目大意: 给出一个n个顶点的无向图,请寻找一条从顶点0出发,遍历其余顶点一次且仅一次.最后回到顶点0的回路——即Hamilton回路. Input 多测试用例.每个测试用例: 第一行,两个正整数 n ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TSH OJ-旅行商TSP)
做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -|| 旅行商(T ...
- 旅行商问题(Traveling Salesman Problem,TSP)的+Leapms线性规划模型及c++调用
知识点 旅行商问题的线性规划模型旅行商问题的+Leapms模型及CPLEX求解C++调用+Leapms 旅行商问题 旅行商问题是一个重要的NP-难问题.一个旅行商人目前在城市1,他必须对其余n-1个城 ...
- 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...
- 洛谷【P1523】旅行商的背包(算法导论 15-1) 题解
P1523 旅行商简化版 题目背景 欧几里德旅行商\((Euclidean Traveling Salesman)\)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有 ...
- Speeding Up The Traveling Salesman Using Dynamic Programming
Copied From:https://medium.com/basecs/speeding-up-the-traveling-salesman-using-dynamic-programming-b ...
随机推荐
- 配置Oracle数据库和监听随Linux系统自启动【转】
配置Oracle数据库和监听随Linux系统自启动 在某些情况下需要在Linux操作系统上提供一种无人值守的随机启动Oracle的功能,目的也许仅仅是为了帮助那些对Oracle细节非常不关心 ...
- 晋升新一线的合肥,跨平台的.NET氛围究竟如何?
大伙可能不知道,2020年合肥已经成功晋升为新一线城市了.本文通过对目前合肥.NET招聘信息以及公众号的相关数据的分析来看下目前合肥.NET的大环境.就着2020中国.NET开发者峰会的顺利举行的东风 ...
- 【C++】《Effective C++》第九章
杂项讨论 条款53:不要轻忽编译器的警告 请记住 严肃对待编译器发出的警告信息.努力在你的编译器的最高(最严苛)警告级别下争取"无任何警告"的容易. 不要过度依赖编译器的报警能力, ...
- 常用的N个网站建议收藏
类型网站路径学习资源及博客论坛网站 书栈网:https://www.bookstack.cn 52 download: http://www.52download.cn/wpcourse/ 菜鸟教程: ...
- 通用寄存器_MOV_ADD_SUB_AND_OR_NOT
通用寄存器 MOV指令 注意:目标操作数与操作数宽度必须一样 MOV 目标操作数,源操作数 作用:拷贝源操作数到目标操作数 1.源操作数可以是立即数.通用寄存器.段寄存器.或者内存单元. 2.目标操作 ...
- 音视频入门-20-BMP、PNG、JPG、GIF静态图生成GIF动态图
* 音视频入门文章目录 * 静态图 -> 动态图 前面 [18-手动生成一张GIF图片] 和 [19-使用giflib处理GIF图片] 生成的 GIF 每一帧都是一个颜色,平时用到的 GIF 每 ...
- Hbase RIT故障修复
业务场景: RocketMQ+Storm+Hbase 组件版本: RocketMQ:3.4.6 Storm:1.2.1 Hbase:1.2.1 1. 问题描述 4月15号早上发现业务系统前一天数据量明 ...
- 【Zabbix】配置zabbix agent向多个server发送数据
1.背景: server端: 172.16.59.197 ,172.16.59.98 agent 端: hostname:dba-test-hzj02 IP:172.16.59.98 2.方式: 配 ...
- webpack知识点整理
作用域 es6里模块化的写法 会存在的问题,变量.方法名字雷同,外部文件调用的时候出现问题 如 a.js里 var a='susan' b.js里 var a='jack' 问题解决方案,添加包裹 a ...
- 类转json的基类实现
类转json的基类实现 项目地址 github地址 实现原理 使用反射获取类的属性名和属性内容.具体原理可以自己查一下资料 对一个类调用getClass().getDeclaredFields()可以 ...