题目链接:点我

问题:

给你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. Docker haproxy应用构建 (五)

    编写dockerfile from centos-base:v1 MAINTAINER 57674891@qq.com RUN mkdir -p /data/{soft,src,logs,script ...

  2. 3.利用jmeter制作性能脚本

        jmeter录制脚本示例   jmeter手工脚本编写与调试   业务逻辑实现之逻辑控制器   业务脚本参数化实现   jmeter处理cookie   beanshell脚本   ...

  3. Session、Cookie与Token

    http协议是无状态协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到 ...

  4. SwiftUI 官方画图实例详细解析

    前言 在前面几篇关于SwiftUI的文章中,我们用一个具体的基本项目Demo来学习了下SwiftUI,里面包含了常见的一些控件使用以及数据处理和地图等等,有兴趣的小伙伴可以去翻翻以前的文章,在前面总结 ...

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

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

  6. SharePoint Online 站点模板中权限的设置

    SharePoint Online可以使用PnP引擎部署站点模板.这个模板的功能非常强大,除了可以定制主题,外观以外,还可以生成list并导入数据,生成文档库,导入文档等等. 今天重点说一下其中的站点 ...

  7. Vue基础之Vue组件

    Vue基础之Vue组件 // 组件是可以复用的Vue实例! // 可以把经常重复的功能封装为组件!

  8. connection-backoff ConnectionBackoff Strategy 回退

    grpc/connection-backoff.md at master · grpc/grpc https://github.com/grpc/grpc/blob/master/doc/connec ...

  9. Connection Pool

    MySQL :: MySQL Connector/NET Developer Guide :: 4.3 Managing a Connection Pool in Connector/NET http ...

  10. [BJOI2016]水晶 做题心得

    [BJOI2016]水晶 做题心得 这是一个写了我两小时的傻逼题.写这个题浪费了一堆时间后,我才意识到我码力又不行了.于是整理起了实现技巧,开始练码力. 思路 不难.首先把 \((x,y,z)\) 变 ...