这个讲的好:

https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95/

分治法

先空着


看一下这个第三个方法(随机增量哈希,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/


Raid POJ - 3714

求两个点集间点距离最小值

开两个哈希表,每次在一个哈希表中查询,然后插入另一个哈希表即可

常数挺大,没有分治快

注意要用%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的更多相关文章

  1. P1429 平面最近点对[加强版] 随机化

    LINK:平面最近点对 加强版 有一种分治的做法 因为按照x排序分治再按y排序 可以证明每次一个只会和周边的六个点进行更新. 好像不算很难 这里给出一种随机化的做法. 前置知识是旋转坐标系 即以某个点 ...

  2. 洛谷 P1429 平面最近点对(加强版) (分治模板题)

    题意:有\(n\)个点对,找到它们之间的最短距离. 题解:我们先对所有点对以\(x\)的大小进行排序,然后分治,每次左右二等分递归下去,当\(l+1=r\)的时候,我们计算一下距离直接返回给上一层,若 ...

  3. Quoit Design (HDU 1007)平面的最近点对

    题目大意:给定平面上的 n 个点,求距离最近的两个点的距离的一半. n <= 10^5.   晕乎乎的度过了一上午... 总之来学习下分治吧233 分治就是把大问题拆成小问题,然后根据对小问题处 ...

  4. Luogu P1429 平面最近点对(加强版)(分治)

    P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行: ...

  5. P1429 平面最近点对(加强版)(分治)

    P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心, ...

  6. p1429 平面最近点对(加强版)

    传送门 分析 我们可以枚举每一个点算它的最近点 估价函数应该分为3种情况计算: 大于max,小于min,位于min和max之间 代码 #include<iostream> #include ...

  7. 洛谷1429 平面最近点对(KDTree)

    qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...

  8. Luogu P1429 平面最近点对 【分治】By cellur925

    题目传送门 题目大意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.$n$<=100000. $Algorithm$ 最朴素的$n^2$枚举肯定 ...

  9. 「LuoguP1429」 平面最近点对(加强版)

    题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y, ...

随机推荐

  1. malloc、calloc、realloc和alloca各种的区别

    需要先包含头文件 #include"malloc.h" malloc是标准的在堆中开辟新的空间 比如 char *pt=(char *)malloc(10*sizeof(char) ...

  2. CSS3学习笔记(4)—上下滑动展开的按钮

    最近写了一个动画,下面来看看我以前写的一个上下滑动展开的按钮效果: 这类的效果经常会在一些网站页面下载按钮处看到,当你鼠标悬浮在下载按钮时,会提醒你是否已注册,或者点击登录什么的小提示~~~~~ 一. ...

  3. github如何提交自己修改的代码

    当在github上发现别人项目有BUG,或者想要完善其功能的时候,该如何把自己的修改提交到项目中呢? 以logback为例 步骤: 1, fork一份logback代码到自己的仓库 进入github要 ...

  4. userData IE

    蛮讨厌IE的,因为他常常需要特别照顾,就像DOM Storage(sessionStorage和localStorage)只能支持IE8+,对于以下的只能使用userData. 原理:通过在docum ...

  5. Linux GCC常用命令学习

    1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...

  6. Azure Key Vault (3) 在Azure Windows VM里使用Key Vaule

    <Windows Azure Platform 系列文章目录> 本章我们介绍如何在Azure Windows VM里面,使用.NET使用Azure Key Vault 我们需要对Key V ...

  7. android jni下c文件怎么输出logcat

    #include <android/log.h> #define LOG_TAG "clog"#define LOGD(...) __android_log_print ...

  8. bzoj3676

    后缀自动机+manacher 听说本质不同的回文串只有O(n)个 那么用manacher求出所有回文串,然后在sam上查找出现了几次就行了 sam的性质又忘了... manacher也忘了... #i ...

  9. SQL 维护计划(自动删除备份文件)

    --开启修改配置功能 exec sp_configure 'allow updates', 0 --启用功能 sp_configure 'xp_cmdshell',1; reconfigure --临 ...

  10. 【eclipse插件开发实战】 Eclipse插件开发5——时间插件Timer开发实例详解

    Eclipse插件开发5--时间插件Timer开发实例详解 这里做的TimeHelper插件设定为在菜单栏.工具栏提供快捷方式,需要在相应地方设置扩展点,最后弹出窗体显示时间. 在上一篇文章里创建好了 ...