(洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714
这个讲的好:
分治法
先空着
看一下这个第三个方法(随机增量哈希,O(n))
1.千万不要用unordered_map/hash_map!T飞是肯定的;要手写哈希表,所以码量就很大;手写哈希表方法记一下
2.事实上以d为边长画格子,每次遍历相邻的9个格子,常数要比以d/2边长画格子,每次遍历相邻25个格子要好(当然此时每个格子里面不一定只有一个数了);不知道为什么
3.注意,用此方法时,如果距离已经为0了,那么就马上跳出循环(不然可能由于除以0或很接近0的数产生非常大的格子编号,产生不好的事情)
4.常数似乎较大,比一些分治法要慢
别人的代码!跑的飞快(交洛谷)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#define MAXN 201000
#define DUBF 999999999.9
#define INF 201007
struct NODE
{
int to;
int next;
};
struct NODE1
{
double x, y;
};
int direction[][] = {, , -, -, -, , -, , , , , , , , , -, , -};
NODE1 point[MAXN];
NODE edges[MAXN];
int ad;
int map[INF];
int HASH(int x, int y)
{
return ((x * MAXN + y) % INF + INF) % INF;
}
double len(int i, int j)
{
return sqrt((point[i].x - point[j].x) * (point[i].x - point[j].x) + (point[i].y - point[j].y) * (point[i].y - point[j].y));
}
void Into_Hash(int i, double r)
{
edges[ad].to = i;
edges[ad].next = map[HASH( (int)(point[i].x/r), (int)(point[i].y/r) )];
map[HASH( (int)(point[i].x/r), (int)(point[i].y/r) )] = ad ++;
}
void Renew_Hash(int n, double r)
{
ad = ;
memset(map, -, sizeof(map));
for(int i = ; i <= n; i ++)
Into_Hash(i, r);
}
double Get_len_around(int p, double r)
{
int x = (int) (point[p].x / r), y = (int) (point[p].y / r), i, j;
double s = DUBF;
for(int k = ; k < ; k ++)
{
i = x + direction[k][], j = y + direction[k][];
for(int q = map[HASH(i, j)]; ~q; q = edges[q].next)
s = s < len(edges[q].to, p) ? s : len(edges[q].to, p);
}
return s;
}
double Get_R(int n)
{
double r = len(, ), s;
int i;
if(r - < 1e- || n < )
return ;
Renew_Hash(, r);
for(i = ; i < n; i ++)
if((s = Get_len_around(i, r)) < r)
{
r = s;
if(r - < 1e-)
return ;
Renew_Hash(i, r);
}
else
Into_Hash(i, r);
return r;
}
void swap(int i, int j)
{
NODE1 t = point[i];
point[i] = point[j];
point[j] = t;
}
int main()
{
int n, i;
while(scanf("%d", &n)==)
{
for(i = ; i < n; i ++)
scanf("%lf %lf", &point[i].x, &point[i].y);
srand((unsigned)time(NULL));
for(i = ; i < n; i ++)
swap(i, rand() % n);
printf("%.4lf\n", Get_R(n));
}
return ; }
自己的代码(跑的慢不少,找不出来原因)(交洛谷)
#pragma GCC optimize("Ofast")
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctime>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef unsigned ul;
typedef pair<ul,ul> puu;
struct P
{
double x,y;
P():x(),y(){}
P(double a,double b):x(a),y(b){}
}p[];
double sqr(double x){return x*x;}
double dis(const P &a,const P &b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
//int dx[]={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,};
//int dy[]={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,};
int dx[]={-,-,-,,,,,,};
int dy[]={-,,,-,,,-,,}; const ul N=;
const ul md=;
ul calc_hash(const puu &x) {return (ull(x.fi)*N%md+x.se)%md;}
template<typename T1,typename T2>
struct hmap
{
struct Node{T1 k;T2 v;int nxt;}e[N+];
int f1[md+],ne;
void ins(const T1 &x,const T2 &y)
{
ul t=calc_hash(x);
e[++ne].k=x;e[ne].v=y;e[ne].nxt=f1[t];f1[t]=ne;
}
}; hmap<puu,P> ma;
int n;
double d;
const double MINX=-1e10,MINY=-1e10;
puu gblock(const P &x)
{
return puu((x.x-MINX)/d,(x.y-MINY)/d);
}
void clr(int n)
{
for(int i=;i<=n;i++) ma.f1[calc_hash(gblock(p[i]))]=;
ma.ne=;
}
void rebuild(int n)
{
for(int i=;i<=n;i++) ma.ins(gblock(p[i]),p[i]);
}
int main()
{
int i,j,k;puu lst,now;double td;
srand(time());
scanf("%d",&n);
for(i=;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
random_shuffle(p+,p+n+);
d=dis(p[],p[]);rebuild();
for(i=;i<=n;i++)
{
if(d<1e-) {d=;break;}
lst=gblock(p[i]);td=1e18;
for(j=;j<;j++)
{
now=mp(lst.fi+dx[j],lst.se+dy[j]);
for(k=ma.f1[calc_hash(now)];k;k=ma.e[k].nxt)
if(ma.e[k].k==now)
td=min(td,dis(ma.e[k].v,p[i]));
}
if(td<d) {clr(i-);d=td;rebuild(i-);}
ma.ins(gblock(p[i]),p[i]);
}
printf("%.4f",d);
return ;
}
(相关:
http://blog.sina.com.cn/s/blog_6fa65cf90100ol2p.html,
http://blog.sina.com.cn/s/blog_aa74c5380101gv0v.html,
https://rjlipton.wordpress.com/2009/03/01/rabin-flips-a-coin/)
求两个点集间点距离最小值
开两个哈希表,每次在一个哈希表中查询,然后插入另一个哈希表即可
常数挺大,没有分治快
注意要用%f输出double
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctime>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef unsigned ul;
typedef pair<ul,ul> puu;
struct P
{
double x,y;bool type;
P():x(),y(){}
P(double a,double b):x(a),y(b){}
}p[];
double sqr(double x){return x*x;}
double dis(const P &a,const P &b)
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
//int dx[]={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,};
//int dy[]={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,};
int dx[]={-,-,-,,,,,,};
int dy[]={-,,,-,,,-,,}; const ul N=;
const ul md=;
ul calc_hash(const puu &x) {return (ull(x.fi)*N%md+x.se)%md;}
template<typename T1,typename T2>
struct hmap
{
struct Node{T1 k;T2 v;int nxt;}e[N+];
int f1[md+],ne;
void ins(const T1 &x,const T2 &y)
{
ul t=calc_hash(x);
e[++ne].k=x;e[ne].v=y;e[ne].nxt=f1[t];f1[t]=ne;
}
}; hmap<puu,P> ma1,ma2;
int n;
double d;
const double MINX=-1e10,MINY=-1e10;
puu gblock(const P &x)
{
return puu((x.x-MINX)/d,(x.y-MINY)/d);
}
void clr(int n)
{
for(int i=;i<=n;i++)
if(p[i].type)
ma2.f1[calc_hash(gblock(p[i]))]=;
else
ma1.f1[calc_hash(gblock(p[i]))]=;
ma1.ne=ma2.ne=;
}
void rebuild(int n)
{
for(int i=;i<=n;i++)
if(p[i].type)
ma2.ins(gblock(p[i]),p[i]);
else
ma1.ins(gblock(p[i]),p[i]);
}
int main()
{
int i,j,k,T;puu lst,now;double td;
hmap<puu,P> *nm1,*nm2;
srand();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=;i<=*n;i++) scanf("%lf%lf",&p[i].x,&p[i].y),p[i].type=(i<=n);
if(n==)
{
printf("%.3f\n",dis(p[],p[]));
goto xxx;
}
swap(p[n+],p[]);
random_shuffle(p+,p+*n+);
d=dis(p[],p[]);rebuild();
for(i=;i<=*n;i++)
{
if(d<1e-) {d=;break;}
nm1=p[i].type?&ma1:&ma2;nm2=p[i].type?&ma2:&ma1;
lst=gblock(p[i]);td=1e18;
for(j=;j<;j++)
{
now=mp(lst.fi+dx[j],lst.se+dy[j]);
for(k=nm1->f1[calc_hash(now)];k;k=nm1->e[k].nxt)
if(nm1->e[k].k==now)
td=min(td,dis(nm1->e[k].v,p[i]));
}
if(td<d) {clr(i-);d=td;rebuild(i-);}
nm2->ins(gblock(p[i]),p[i]);
}
printf("%.3f\n",d);
clr(*n);
xxx:;
}
return ;
}
upd:这个基于哈希表的随机增量好像不是很对?哈希表的空间开不到O(n^2)啊,冲突概率怕是会很高?(然而实测还行啊?)
(洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714的更多相关文章
- P1429 平面最近点对[加强版] 随机化
LINK:平面最近点对 加强版 有一种分治的做法 因为按照x排序分治再按y排序 可以证明每次一个只会和周边的六个点进行更新. 好像不算很难 这里给出一种随机化的做法. 前置知识是旋转坐标系 即以某个点 ...
- 洛谷 P1429 平面最近点对(加强版) (分治模板题)
题意:有\(n\)个点对,找到它们之间的最短距离. 题解:我们先对所有点对以\(x\)的大小进行排序,然后分治,每次左右二等分递归下去,当\(l+1=r\)的时候,我们计算一下距离直接返回给上一层,若 ...
- Quoit Design (HDU 1007)平面的最近点对
题目大意:给定平面上的 n 个点,求距离最近的两个点的距离的一半. n <= 10^5. 晕乎乎的度过了一上午... 总之来学习下分治吧233 分治就是把大问题拆成小问题,然后根据对小问题处 ...
- Luogu P1429 平面最近点对(加强版)(分治)
P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行: ...
- P1429 平面最近点对(加强版)(分治)
P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心, ...
- p1429 平面最近点对(加强版)
传送门 分析 我们可以枚举每一个点算它的最近点 估价函数应该分为3种情况计算: 大于max,小于min,位于min和max之间 代码 #include<iostream> #include ...
- 洛谷1429 平面最近点对(KDTree)
qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...
- Luogu P1429 平面最近点对 【分治】By cellur925
题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定 ...
- 「LuoguP1429」 平面最近点对(加强版)
题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y, ...
随机推荐
- [usaco2003feb]impster
FJ再也不用野蛮的方式为自己的奶牛编号了.他用一个B(1<=B<=16)位二进制编码给每头奶牛编号,并刻在奶牛耳朵上的金属条上.奶牛希望自己给自己选择一个编码.于是,瞒着FJ,他们制造了一 ...
- git使用笔记(四)错误报告 Git push rejected error: fatal: refusing to merge unrelated histories
Reason: The reason is because I created repo in Github with initiated README.md file, and I tried to ...
- 人生苦短之Python多线程
#encoding=utf-8 import threading import time ''' python多线程并不是真正意义上的多线程,通常我们所说的多线程是多个线程同时执行某功能,而在pyth ...
- RobotFramework教程使用笔记——RobotFramework的安装配置
(一) Python的安装和pip配置 首先,从Python的官方网站 www.python.org http://www.python.org/ftp/python 然后,运行下载的MSI安装包, ...
- 「AHOI2008」「LuoguP4281」紧急集合 / 聚会(LCA
题目描述 欢乐岛上有个非常好玩的游戏,叫做“紧急集合”.在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要 ...
- [ZJOI 2013] K大数查询
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3110 [算法] 整体二分 + 线段树 时间复杂度 : O(NlogN ^ 2) [代 ...
- doc命令大全
不是原创的,但基本上收入了各个网站dos命令了基本上可以作为电子书使用,希望对各位有用net use \\ip\ipc$ " " /user:" " 建立IPC ...
- C语言指针入门知识
C语言指针往往是C语言学习过程中最困难的地方, 最近重新理解了一下C语言的指针知识, 在此整理一下, 如果有错误请留言指正. 对于刚入门的人来说, 指针涉及方方面面, 从简单的数组到结构体, 都会用到 ...
- Beyond Compare 简体版+注册码
Beyond Compare 3.3.4.14431 官方简体版+注册码 查阅全文 ›
- 【225】ArcEngine 实现要素添加 & 删除
参考:ArcGIS Engine效率探究——要素的添加和删除.属性的读取和更新 删除要素 //添加图层,显示在最上面 axMapControl1.AddShapeFile(@"D:\01-业 ...