这道题一开始想的是用Dijkstra或者是SPFA算法来写,写好了以后提交,结果TLE了。当时写的时候就感觉每个节点更新的复杂度至少是 O(n) O(n) 级别的,再考虑到数据量有 N<=100000,0<=Xi,Yi<=1000000000 N 就感觉会超时,不过当时也不知道该怎么降维,只能硬着头皮上了。后来看了hihocoder上面的题解后

http://www.hihocoder.com/discuss/question/2792

知道了怎么将 O(n) O(n) 降为 O(4) O(4) ,重新写了以后,就AC了。
  首先我来讲讲 O(n) O(n) 的算法是个什么思路,不想看的朋友可以直接看下一段。在SPFA算法中,在某个节点 i i从队列中弹出来后,我们需要将跟这个节点相连的节点最短路径进行更新,然后将路径长度变短的节点重新塞入队列中。这样一来,由于每个节点都可以跟节点ii相连,所以需要将所有的节点都进行一遍更新,也就是每个节点的更新复杂度是 O(n) O(n) ,在这样大的数据量的情况下,跑完整个list肯定就会超时了。因此现在就需要降维。
  看了hihocoder的题解,简单来说,就是分别找到在X和Y上距离每个节点最近的两个节点(一前一后),然后在每次更新相邻节点时,就只用更新前后4个,也就是 O(4) O(4) 的复杂度了。因此我们需要对X进行排序,找到该节点的一前一后两个点(X数值相同也行);同理对Y进行处理。之后每次更新只用找到这4个点更新就行。为了更进一步进行优化,我还做了剪枝处理,设置一个1到N的距离最大值maxDistance,如果两个点的距离大于这个值,就直接丢弃,不需要在访问了。并且需要对maxDistance进行维护,更新。下面就是AC代码:
  

//Islands Trave
#include<iostream>
//#include<map>
//#include<string>
#include<queue>
#include<vector>
#include <cstdio>
#include<fstream>
#include<algorithm>
using namespace std;#define Min(a,b) a<b?a:b
#define INF 1000000005
#define Num 100000+5
typedef struct {//每个节点的结构int X;int Y;int ID;int LinkNode[4];//分别对应X上的一前一后和Y上的一前一后,beforeX, afterX,beforeY, afterY
} Location;Location location[Num];
int head[Num];
queue<int> list;
bool visit[Num];
int Distance[Num];int differ(int l1, int l2)//计算两个节点的距离
{if (l1 == l2) return INF;return Min(abs(location[l1].X - location[l2].X), abs(location[l1].Y - location[l2].Y));
}bool compx(Location l1, Location l2)///按照X对节点进行排序
{if (l1.X != l2.X) return l1.X < l2.X;else return  l1.Y < l2.Y;
}bool compy(Location l1, Location l2)//按照Y对节点进行排序
{if (l1.Y != l2.Y) return l1.Y < l2.Y;else return  l1.X < l2.X;
}bool compID(Location l1, Location l2)//按照ID对节点进行排序
{return l1.ID < l2.ID;
}int LuShi()
{int N = 0, maxDistance = 1000000000;cin >> N;int i = 0, j = 0;for (i = 1; i < N + 1; i++){cin >> location[i].X >> location[i].Y;location[i].ID = i;visit[i] = false;Distance[i] = INF;}sort(location + 1, location + N + 1, compx);//对X进行排序i = 1;location[i].LinkNode[0] = 0;while (i<N + 1){j = i + 1;location[j].LinkNode[0] = location[i].ID;//beforeX,在X上的前一个location[i].LinkNode[1] = j <= N ? location[j].ID : 0;//afterX,在X上的后一个i++;}sort(location + 1, location + N + 1, compy);//对Y进行排序i = 1;location[j].LinkNode[2] = 0;while (i < N + 1){j = i + 1;location[j].LinkNode[2] = location[i].ID;//beforeY,在Y上的前一个location[i].LinkNode[3] = j <= N ? location[j].ID : 0;//afterY,在Y上的后一个i++;}sort(location + 1, location + N + 1, compID);//恢复原来的顺序,方便查找maxDistance = differ(1,N);//计算最大值,准备剪枝for (int i = 1; i < N + 1; i++)//对1节点进行更新,将周围4个节点塞入队列{if (differ(1, i)<maxDistance) {Distance[i] = differ(1, i);list.push(i);visit[i] = true;}}while (!list.empty()){for (i = 0; i < 4; i++)//可以看到,这个复杂度是O(4){int to = location[list.front()].LinkNode[i];//相邻的节点int min = differ(list.front(), to) + Distance[list.front()];//计算1到该节点的最短距离if (min<maxDistance) {//如果这一跳距离大于1到N的距离,那么最后通过这个路径到达N的距离一定大于等于maxDistance,剪枝if (min < Distance[to]) {//只有小于原来的距离才剪枝if (to == N) {//如果相邻节点是N,更新最短距离maxDistancemaxDistance = min;}else//不是到N的,将这个节点塞入队列{if (visit[to] == false) {//如果在队列中,就不需要塞了list.push(to);visit[to] = true;}}Distance[to] = min;//更新相邻节点的最短距离}}}visit[list.front()] = false;//弹出节点list.pop();}cout << Distance[N] << endl;//直接输出N的值return 0;
}int main()
{streambuf * oldbuf = cin.rdbuf((new ifstream("C:\\Users\\yzc\\Desktop\\input.txt"))->rdbuf());//重定向,OJ时将它注释掉//cout << LuShi() << endl;LuShi();system("pause");return 0;
}

hihocoder #1138 : Islands Trave相关推荐

  1. hihocoder 1038

    http://hihocoder.com/problemset/problem/1138 题意:有一些岛屿,要从第一个岛屿到第N个岛屿,求最短距离,距离为min(x,y),也就是两个点的X的差值和Y的 ...

  2. 构造 Codeforces Round #302 (Div. 2) B Sea and Islands

    题目传送门 1 /* 2 题意:在n^n的海洋里是否有k块陆地 3 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 4 输出完k个L后,之后全部输出S:) 5 5 10 的例子可以 ...

  3. hihoCoder 网络流四·最小路径覆盖

    题面带解释 hihoCoder感觉很好. 网络流的精华就是建图 #include<cstdio> #include<iostream> #include<algorith ...

  4. 1138: 零起点学算法45——求最大值

    1138: 零起点学算法45--求最大值 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lld Submitted: 1691  ...

  5. hihoCoder #1142 : 三分求极值

    #1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一 ...

  6. hihocoder 后缀自动机专题

    一.后缀自动机基本概念的理解 1.首先后缀自动机的状态是由子串的endpos来决定的 子串的endpos是指一个子串可以在原字符串的哪些位置进行匹配, endpos构成的不同集合划分成不同的状态 关于 ...

  7. hihoCoder 1051 补提交卡(贪心,枚举)

    #1051 : 补提交卡 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho给自己定了一个宏伟的目标:连续100天每天坚持在hihoCoder上提交一个程序.100天过 ...

  8. 200.Number of Islands

    /** 200.Number of Islands * 2016-4-3 by Mingyang* union 什么:两个相邻的1元素* union 目的:union后计数union集合数量(通过计数 ...

  9. hihoCoder week3 KMP算法

    题目链接 https://hihocoder.com/contest/hiho3/problems kmp算法 #include <bits/stdc++.h> using namespa ...

最新文章

  1. 学python编程-趣学python编程中文版 PDF 下载
  2. set,env,和export的区别
  3. 2019 DDCTF 部分writeup
  4. Redis的哨兵模式Sentinel
  5. 计算机意外关闭原因 安全问题,win7弹出“计算机意外地重新启动或遇到错误”处理方法...
  6. 尝试用LoadRunner录制单机程序--未生成录制脚本
  7. GEO基因芯片数据处理精华(一):GEOquery包
  8. limbo pc for android,「Limbo PC emulator」可以让安卓手机安装 Windows 10 了
  9. ubuntu装指定分区_Ubuntu安装时怎样分区
  10. Linux版本怎么设置指纹,Linux上使用Thinkpad指纹识别
  11. 如何把多个PDF页面合并成一页PDF - PDF页面合并器使用方法
  12. “磁碟机”病毒分析报告
  13. 小米人APK改之理(APK IDE)
  14. 强化学习:Markov Decision Process (基于南大俞扬博士演讲的修改和补充)
  15. GNU Radio Pythpn
  16. 漫威超级争霸战辅助脚本,快速刷星币打竞技场副本
  17. 废土行动最新服务器机柜销售,《废土行动》避难所 你想要知道的信息我们一次都告诉你...
  18. y160.第九章 GitOps从入门到精通 -- Tekton Trigger(九)
  19. matlab三相短路电流计算程序_三相短路电流计算
  20. jTessBoxEditor2.3.1训练字库

热门文章

  1. 计算机毕业设计选题参考【系统、论文】
  2. 企业常用mysql集群软件_mysql企业常用集群架构
  3. 人工智能知识全面讲解:感知机原理
  4. 使用Logistic Regression进行文本分类
  5. 2021年施工升降机司机(建筑特殊工种)考试资料及施工升降机司机(建筑特殊工种)证考试
  6. 配置 Haproxy 负载均衡群集
  7. 内部排序(八)主位优先基数排序
  8. 指针的进阶应用之双指针、三指针
  9. maven获得dom4j_org.dom4j maven
  10. OpenGL坐标变换及其数学原理,两种摄像机交互模型(附源程序)