zoukankan      html  css  js  c++  java
  • 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
    ", result);
    	return 0;
    }
    
  • 相关阅读:
    sdk 今日头条_字节跳动又一Android开源力作!全新视频动画特效SDK
    Android播放透明视频(转载)
    git remote: warning: suboptimal pack
    'gitclone报错fatal:protocolerror:badpackheader'
    解决 Maven 无法下载 fastdfs-client-java 依赖。
    教我兄弟学Android逆向12 编写xposed模块
    教我兄弟学Android逆向11 动态调试init_array
    CommunicationsException
    使用css给table表格表头添加斜线(斜线表格)
    [SAA + SAP] 28. Monitoring
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5686562.html
Copyright © 2011-2022 走看看