题目链接:点我

问题:

给你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)问题的更多相关文章

  1. 遗传算法的简单应用-巡回旅行商(TSP)问题的求解

    上篇我们用遗传算法求解了方程,其中用到的编码方式是二进制的编码,实现起来相对简单很多, 就连交配和变异等操作也是比较简单,但是对于TSP问题,就稍微复杂一点,需要有一定的策略, 才能较好的实现. 这次 ...

  2. 二进制状态压缩dp(旅行商TSP)POJ3311

    http://poj.org/problem?id=3311 Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Subm ...

  3. Hamilton回路 旅行商TSP问题 /// dp oj1964

    题目大意: 给出一个n个顶点的无向图,请寻找一条从顶点0出发,遍历其余顶点一次且仅一次.最后回到顶点0的回路——即Hamilton回路. Input 多测试用例.每个测试用例: 第一行,两个正整数 n ...

  4. 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法

    若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...

  5. ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TSH OJ-旅行商TSP)

    做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -|| 旅行商(T ...

  6. 旅行商问题(Traveling Salesman Problem,TSP)的+Leapms线性规划模型及c++调用

    知识点 旅行商问题的线性规划模型旅行商问题的+Leapms模型及CPLEX求解C++调用+Leapms 旅行商问题 旅行商问题是一个重要的NP-难问题.一个旅行商人目前在城市1,他必须对其余n-1个城 ...

  7. 【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 01 什么是旅行商问题(TS ...

  8. 洛谷【P1523】旅行商的背包(算法导论 15-1) 题解

    P1523 旅行商简化版 题目背景 欧几里德旅行商\((Euclidean Traveling Salesman)\)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有 ...

  9. Speeding Up The Traveling Salesman Using Dynamic Programming

    Copied From:https://medium.com/basecs/speeding-up-the-traveling-salesman-using-dynamic-programming-b ...

随机推荐

  1. python模块详解 | shutil

    简介: shutil是python的一个内置模块,提供了许多关于文件和文件集合的高级操作,特别提供文件夹与文件操作.归档操作了支持文件复制和删除的功能. 文件夹与文件操作: copyfileobj(f ...

  2. ES6 自定义一个实现了Iterator接口的对象

    参考资料 var obj = { data: [1,2,3,4,5], // 这里实际上就是去定义如何实现Iterator接口 [Symbol.iterator](){ const that = th ...

  3. Java JDK8下载 (jdk-8u251-windows-x64和jdk-8u271-linux-x64.tar)

    jdk-8u251-windows-x64 和 jdk-8u271-linux-x64.tar 链接:https://pan.baidu.com/s/1gci6aSIFhEhjY8F48qH39Q 提 ...

  4. Java高并发与多线程(二)-----线程的实现方式

    今天,我们开始Java高并发与多线程的第二篇,线程的实现方式. 通常来讲,线程有三种基础实现方式,一种是继承Thread类,一种是实现Runnable接口,还有一种是实现Callable接口,当然,如 ...

  5. 【Linux】centos7中 root家目录中perl5文件夹无法删除问题解决

    由于新项目上线,安装了一些perl的一些包 但是发现,在/root下有一个perl5/的文件夹,删除后,重新登录又会出现,很是烦人,而且他还没有内容,就是一个空文件 那么着手搞掉他 环境:centos ...

  6. ctfshow—web—web签到题

    打开靶机,发现只有一句话 查看源码 发现一段字符串,猜是base64加密 拿到flag

  7. elasticsearch-head:5连接elasticsearch 6.x无法显示浏览数据的解决方案

    问题 在docker安装了elasticsearch-head:5和elasticsearch:6.3.2 打开界面连接es时发现数据无法展示. 解决方案 因docker使用的版本问题,可能名称略有变 ...

  8. 转 1 认识开源性能测试工具jmeter

    1 认识开源性能测试工具jmeter   典型的性能测试工具主要有2个,Load Runner和jmeter.Load Runner是商业化的,Jmeter是开源的.下面我们认识一下开源性能测试工具j ...

  9. chain issues incorrect order,EXtra certs,Contains anchor

    背景: 下载颁发下来的ssl证书安装好之后网站正常显示安全,但是通过ssl证书网站去检测报错误:chain issues incorrect order,EXtra certs,Contains an ...

  10. LinuxCentos7下安装Mysql8.x以及密码修改

    LinuxCentos7下安装Mysql以及密码修改 引言: 之前都是用Docker或者yum自动安装,这次主要是下载压缩包解压安装,中间也有些小波折,记录如下,以供参考: 1.删除旧的MySQL 检 ...