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的更多相关文章
随机推荐
- h264
H264--编码原理以及I帧B帧P帧--1 前言 ----------------------- H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论 ...
- Python学习笔记-Day3-python内置函数
python内置函数 1.abs 求绝对值 2.all 判断迭代器中的所有数据是否都为true 如果可迭代的数据的所有数据都为true或可迭代的数据为空,返回True.否则返回False 3.a ...
- JAVA基础知识之JVM-——动态代理(AOP)
代理模式简介 在很多场景下,我们想使用一个类(通常是接口)A时,并不是直接使用这个类,而是通过另外一个类B去调用A的方法,这里的类B就是一个代理类. 有很多场景都会用到这种方法,例如假如创建类A需要很 ...
- Poj(1797) Dijkstra对松弛条件的变形
题目链接:http://poj.org/problem?id=1797 题意:从路口1运货到路口n,最大的运货重量是多少?题目给出两路口间的最大载重. 思路:j加到s还是接到K下面,取两者的较大者,而 ...
- Android 内存分析工具 - LogCat GC
一.GC_Reason 触发垃圾回收的回收的集中原因: 类型 描述 GC_CONCURRENT 内存使用将满时,并发的进行垃圾回收. GC_FOR_MALLOC 当内存已满应用尝试分配内存时会出触发垃 ...
- poj3349
http://poj.org/problem?id=3349 每个雪花都有六个分支,用六个整数代表,这六个整数是从任意一个分支开始,朝顺时针或逆时针方向遍历得到的.输入多个雪花,判断是否有形状一致的雪 ...
- IMetadataAware接口的特性定制Model元数据
第一步创建元数据类 using System; using System.Collections.Generic; using System.Linq; using System.Reflection ...
- 编译android源码官方教程(2)建立编译环境「linux & mac osx」
https://source.android.com/source/initializing.html Establishing a Build Environment IN THIS DOCUMEN ...
- hdu 5643 King's Game 约瑟夫变形
首先约瑟夫问题的数学推理过程:我们知道第一个人(编号一定是(m-1) mod n) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m mod n的人开始):k k+1 k+2 ... ...
- FLASH CC 2015 CANVAS 中 createjs 移除绑定事件
myBtn.addEventListener("click", function(evt) { // do stuff... evt.remove(); // removes th ...