hihocoder #1138 : Islands Trave
这道题一开始想的是用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相关推荐
- hihocoder 1038
http://hihocoder.com/problemset/problem/1138 题意:有一些岛屿,要从第一个岛屿到第N个岛屿,求最短距离,距离为min(x,y),也就是两个点的X的差值和Y的 ...
- 构造 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 的例子可以 ...
- hihoCoder 网络流四·最小路径覆盖
题面带解释 hihoCoder感觉很好. 网络流的精华就是建图 #include<cstdio> #include<iostream> #include<algorith ...
- 1138: 零起点学算法45——求最大值
1138: 零起点学算法45--求最大值 Time Limit: 1 Sec Memory Limit: 64 MB 64bit IO Format: %lld Submitted: 1691 ...
- hihoCoder #1142 : 三分求极值
#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一 ...
- hihocoder 后缀自动机专题
一.后缀自动机基本概念的理解 1.首先后缀自动机的状态是由子串的endpos来决定的 子串的endpos是指一个子串可以在原字符串的哪些位置进行匹配, endpos构成的不同集合划分成不同的状态 关于 ...
- hihoCoder 1051 补提交卡(贪心,枚举)
#1051 : 补提交卡 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho给自己定了一个宏伟的目标:连续100天每天坚持在hihoCoder上提交一个程序.100天过 ...
- 200.Number of Islands
/** 200.Number of Islands * 2016-4-3 by Mingyang* union 什么:两个相邻的1元素* union 目的:union后计数union集合数量(通过计数 ...
- hihoCoder week3 KMP算法
题目链接 https://hihocoder.com/contest/hiho3/problems kmp算法 #include <bits/stdc++.h> using namespa ...
最新文章
- 学python编程-趣学python编程中文版 PDF 下载
- set,env,和export的区别
- 2019 DDCTF 部分writeup
- Redis的哨兵模式Sentinel
- 计算机意外关闭原因 安全问题,win7弹出“计算机意外地重新启动或遇到错误”处理方法...
- 尝试用LoadRunner录制单机程序--未生成录制脚本
- GEO基因芯片数据处理精华(一):GEOquery包
- limbo pc for android,「Limbo PC emulator」可以让安卓手机安装 Windows 10 了
- ubuntu装指定分区_Ubuntu安装时怎样分区
- Linux版本怎么设置指纹,Linux上使用Thinkpad指纹识别
- 如何把多个PDF页面合并成一页PDF - PDF页面合并器使用方法
- “磁碟机”病毒分析报告
- 小米人APK改之理(APK IDE)
- 强化学习:Markov Decision Process (基于南大俞扬博士演讲的修改和补充)
- GNU Radio Pythpn
- 漫威超级争霸战辅助脚本,快速刷星币打竞技场副本
- 废土行动最新服务器机柜销售,《废土行动》避难所 你想要知道的信息我们一次都告诉你...
- y160.第九章 GitOps从入门到精通 -- Tekton Trigger(九)
- matlab三相短路电流计算程序_三相短路电流计算
- jTessBoxEditor2.3.1训练字库