hiho_1138_island_travel
题目
二维平面上有n个点,每个点的横纵坐标均为非负整数。两个点之间的距离记为 min(abs(x1 - x2), abs(y1 - y2)),求从点1到达点n的最短路径长度。
比较容易想到使用最短路径算法来解决,但关键的问题是如何建图!参考了网上的代码http://blog.csdn.net/chenzhenyu123456/article/details/50650029
实现
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<algorithm>
using namespace std;
const int kMaxNodes = 100005;
//节点结构体,用于记录点的横纵坐标,以及序号
struct Node{
int x;
int y;
int id;
};
Node gNodes[kMaxNodes];
//对节点按照横坐标进行排序,比较函数
bool Cmp1(const Node& node1, const Node& node2){
if (node1.x == node2.x)
return node1.y < node2.y;
return node1.x < node2.x;
}
//对节点按照纵坐标进行排序,比较函数
bool Cmp2(const Node& node1, const Node& node2){
if (node1.y == node2.y)
return node1.x < node2.x;
return node1.y < node2.y;
}
//边结构体,用于构建图
struct Edge{
int to;
int dist;
int next;
};
//求最短路的节点结构体,id表示点的序号,dist为从源点到达该点的最短距离
struct SpNode{
int id;
int dist;
SpNode(int i = 0, int d = 0) :id(i), dist(d){};
};
//比较函数,用于dijkstra中对源点到点的排序
struct Cmp{
bool operator()(const SpNode& node1, const SpNode& node2){
return node1.dist > node2.dist;
}
}; Edge gEdges[4 * kMaxNodes];
int gEdgeIndex;
int gHead[kMaxNodes];
bool gVisited[kMaxNodes];
int gMinDist[kMaxNodes]; //记录从源点到达点的最短距离
void Init(){
gEdgeIndex = 0;
memset(gEdges, -1, sizeof(gEdges));
memset(gHead, -1, sizeof(gHead));
memset(gVisited, false, sizeof(gVisited));
memset(gMinDist, -1, sizeof(gMinDist));
}
void InsertEdge(int u, int v, int d){
int e = gEdgeIndex++;
gEdges[e].to = v;
gEdges[e].dist = d;
gEdges[e].next = gHead[u];
gHead[u] = e;
} int Dijkstra(int n){
priority_queue<SpNode, vector<SpNode>, Cmp> pq;
SpNode node;
node.id = 0;
gMinDist[0] = node.dist = 0;
pq.push(node);
while (!pq.empty()){
node = pq.top();
pq.pop();
int u = node.id;
if (gVisited[u])
continue;
gVisited[u] = true;
if (u == n-1)
break;
for (int e = gHead[u]; e != -1; e = gEdges[e].next){
int v = gEdges[e].to;
if (gMinDist[v] == -1 || gMinDist[v] > gMinDist[u] + gEdges[e].dist){
gMinDist[v] = gMinDist[u] + gEdges[e].dist;
pq.push(SpNode(v, gMinDist[v]));
}
}
}
return gMinDist[n-1];
}
int main(){
int n, x, y;
Init();
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%d %d", &gNodes[i].x, &gNodes[i].y);
gNodes[i].id = i;
}
//建图
/*
先对所有点的横坐标进行排序,有些点的横坐标相同,则将这些点浓缩成一个点,同时选择这些点中id最小的作为该集合的代表。
集合内的各个点和代表点之间添加长度为0的边;
集合的代表点之间添加边,边的长度为点的横坐标的差值,但是并不需要所有的代表点之间都添加边,只需要在相邻的集合之间添加边。
因为如果 i,j,k分别为三个集合的代表点,i和j相邻,j和k相邻,从i到k的路径等于从i到j的路径和从j到k的路径之和(如果单看横坐标)。
在用dijkstra算法求最短路径的时候只通过i到j,j到k即可,不需要额外添加i到k的边了。 同样,对所有点按照纵坐标进行排序.....添加边 最后,在构造完成的图上运用dijkstra算法求最短路径即可。
*/
sort(gNodes, gNodes + n, Cmp1);
int i = 0, j;
while (i < n-1){
j = i + 1;
while (gNodes[i].x == gNodes[j].x){
InsertEdge(gNodes[i].id, gNodes[j].id, 0);
InsertEdge(gNodes[j].id, gNodes[i].id, 0);
j++;
}
if (j >= n)
break;
InsertEdge(gNodes[i].id, gNodes[j].id, gNodes[j].x - gNodes[i].x);
InsertEdge(gNodes[j].id, gNodes[i].id, gNodes[j].x - gNodes[i].x);
i = j;
}
i = 0;
sort(gNodes, gNodes + n, Cmp2);
while (i < n-1){
j = i + 1;
while (gNodes[i].y == gNodes[j].y){
InsertEdge(gNodes[i].id, gNodes[j].id, 0);
InsertEdge(gNodes[j].id, gNodes[i].id, 0);
j++;
}
if (j >= n)
break;
InsertEdge(gNodes[i].id, gNodes[j].id, gNodes[j].y - gNodes[i].y);
InsertEdge(gNodes[j].id, gNodes[i].id, gNodes[j].y - gNodes[i].y);
i = j;
}
int result = Dijkstra(n);
printf("%d\n", result);
return 0;
}
hiho_1138_island_travel的更多相关文章
随机推荐
- 使用oracle写if判断
DECLARE L_X INT; BEGIN SELECT COUNT(*) INTO L_X FROM SYSTEMROLEFUNCTION WHERE ROLEID = '1'; IF L_X & ...
- Python学习笔记-Day2-Python基础之字典操作
字典的常用操作包括但不限于以下操作: 字典的字典的索引,新增,删除,循环,长度等等 这里将对列表的内置操作方法进行总结归纳,重点是以示例的方式进行展示. 使用type获取创建对象的类 type(dic ...
- httpclient请求方法
/** * httpclient请求方法 * @param url 请求地址 * @param paramMap 请求参数 * @param ent 编码格式 gbk.utf-8 * @return ...
- 切分vocab时遇到的问题
vocab的格式如下所示,每个词和对应100维的向量: </s> 0.004003 0.004419 -0.003830 -0.003278 0.001367 0.003021 0.000 ...
- 精通D3.js学习笔记(2)比例尺和坐标
1.线性比例尺 d3.scale.linear() 创建一个线性比例尺 .domain([0,500]) 定义域 .range([0,1000]) 值域 l ...
- Mysql-学习笔记(==》事件 十二)
事件 计划任务(定期定时执行) -- 查看当前mysql数据库是否开启时间功能,默认关闭SHOW VARIABLES LIKE 'event_scheduler'; -- event_schedule ...
- html body的属性 格式控制标签 内容容器标签 超链接标签 图片标签 表格
一.body的属性 <body bgcolor 页面背景色 background 背景壁纸.图片 text文字颜色 topmargin上边距 leftmargin左边距 rightmargi ...
- Flume-NG + HDFS + HIVE日志收集分析
摘自:http://blog.csdn.net/cnbird2008/article/details/18967449
- c语言中函数调用的本质从汇编角度分析
今天下午写篇博客吧,分析分析c语言中函数调用的本质,首先我们知道c语言中函数的本质就是一段代码,但是给这段代码起了一个名字,这个名字就是他的的这段代码的开始地址 这也是函数名的本质,其实也就是汇编中的 ...
- python3.5.1语法
1.print (变量名) print("字符串") 2.a=1 id(a)返回a在内存中的地址 3.可以用table弹出提示 #coding:utf-8 4.输入3/2 结果 ...