Description

After successive failures in the battles against the Union, the Empire retreated to its last stronghold. Depending on its powerful defense system, the Empire repelled the six waves of Union's attack. After several sleepless nights of thinking, Arthur, General of the Union, noticed that the only weakness of the defense system was its energy supply. The system was charged by N nuclear power stations and breaking down any of them would disable the system.

The general soon started a raid to the stations by N special agents who were paradroped into the stronghold. Unfortunately they failed to land at the expected positions due to the attack by the Empire Air Force. As an experienced general, Arthur soon realized that he needed to rearrange the plan. The first thing he wants to know now is that which agent is the nearest to any power station. Could you, the chief officer, help the general to calculate the minimum distance between an agent and a station?

Input

The first line is a integer T representing the number of test cases.

Each test case begins with an integer N (1 ≤ N ≤ 100000).

The next N lines describe the positions of the stations. Each line consists of two integers X (0 ≤ X ≤ 1000000000) and Y (0 ≤ Y ≤ 1000000000) indicating the positions of the station.

The next following N lines describe the positions of the agents. Each line consists of two integers X (0 ≤ X ≤ 1000000000) and Y (0 ≤ Y ≤ 1000000000) indicating the positions of the agent.

看不懂题面没有关系,我来大致讲一下:给定平面上n个黑点和n个白点(就这样认为吧),求最近的黑点与白点之间的距离。多组输入。输出保留三位小数。

其实这题就是裸的平面最近点对,只需把相同颜色的点之间的距离设为INF即可。

我在这里不做详解,只是稍稍讲一下怎么做。

首先,最近点对 对于一个区间(x坐标)显然 有三种情况:全都在中线左边,全都在中线右边,或者一个在左一个在右。而前两种显然可以递归处理。

那么,我们只需先把点按x坐标排序,然后处理过中线的点对即可。我们定义solve(l,r)来计算在l个点到第r个点之间的最近点对,那么solve(l,r)=min{solve(l,mid),solve(mid+1,r),过中线的最小值}

于是,我们发现在求过中线的最近点对之前我们已经知道了当前的最优解now。由于距离<=now的点离中线的距离一定<=now,那么我们可以把左右两边符合条件的点分别先抠出来。

现在问题变成了:对于任意一个点,是否有点在以它为半径,now为圆心的圆内?

但圆内的点并不好求,我们就可以把圆拓展成矩形:



我们可以发现些什么?是不是最多只有6个点在这些矩形内?

把点再按y轴排一遍序,对于每个点弄个上下边界,一路扫过去即可。总的复杂度为O(nlogn)。

还有一件事:这道题居然卡精度!卡精度!卡精度!请注意你的精度!

当然还有一件非常鬼畜的事(c++选手):POJ上用printf("%.3lf")时就一直WA,改成printf("%.3f")才可以AC。不知所措。

下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 200010
#define INF (1LL<<60) using namespace std;
typedef long long llg; struct data{
int x,y; bool w;
bool operator < (const data &h)const{return x<h.x;}
}s[maxn],ss[maxn];
llg ans,now;
int n,a[maxn],b[maxn],la,lb,T; inline llg ji(int x){return (llg)x*(llg)x;}
inline llg dis(int x,int y){ return s[x].w==s[y].w?INF:ji(s[x].x-s[y].x)+ji(s[x].y-s[y].y);} void work(){
for(int i=1,l=1,r=1;i<=la;i++){
while(s[b[r]].y-s[a[i]].y<now && r<=lb) r++;
while(s[a[i]].y-s[b[l]].y>now && l<=lb) l++;
for(int j=l;j<r;j++) ans=min(ans,dis(a[i],b[j]));
}
} void solve(int l,int r){
if(l==r) return;
int mid=l+r>>1;
llg m=s[mid].x; now=(llg)sqrt(ans);
solve(l,mid); solve(mid+1,r);
la=0,lb=0;
for(int i=l;i<=mid;i++)
if(m-s[i].x<now) a[++la]=i;
for(int i=mid+1;i<=r;i++)
if(s[i].x-m<now) b[++lb]=i;
work();
int k1=l,k2=mid+1,kk=l-1;
while(k1<=mid && k2<=r)
if(s[k1].y<=s[k2].y) ss[++kk]=s[k1++];
else ss[++kk]=s[k2++];
while(k1<=mid) ss[++kk]=s[k1++];
while(k2<=r) ss[++kk]=s[k2++];
for(int i=l;i<=r;i++) s[i]=ss[i];
} int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n); ans=INF;
for(int i=1;i<=n*2;i++){
scanf("%d %d",&s[i].x,&s[i].y);
s[i].w= i<=n;
}
sort(s+1,s+n*2+1); solve(1,n<<1);
printf("%.3f\n",sqrt(ans));
}
}

POJ 3714 Raid的更多相关文章

  1. 最近点对问题 POJ 3714 Raid && HDOJ 1007 Quoit Design

    题意:有n个点,问其中某一对点的距离最小是多少 分析:分治法解决问题:先按照x坐标排序,求解(left, mid)和(mid+1, right)范围的最小值,然后类似区间合并,分离mid左右的点也求最 ...

  2. poj 3714 Raid【(暴力+剪枝) || (分治法+剪枝)】

    题目:  http://poj.org/problem?id=3714 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=27048#prob ...

  3. poj 3714 Raid(平面最近点对)

    Raid Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7473   Accepted: 2221 Description ...

  4. POJ 3714 Raid(计算几何の最近点对)

    Description After successive failures in the battles against the Union, the Empire retreated to its ...

  5. POJ 3714 Raid 近期对点题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/.未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

  6. POJ 3714 Raid(平面近期点对)

    解题思路: 分治法求平面近期点对.点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cst ...

  7. (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714

    这个讲的好: 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 ...

  8. 【POJ 3714】 Raid

    [题目链接] http://poj.org/problem?id=3714 [算法] 分治求平面最近点对 [代码] #include <algorithm> #include <bi ...

  9. 【POJ 3714】Raid

    [题目链接]:http://poj.org/problem?id=3714 [题意] 给你两类的点; 各n个; 然后让你求出2*n个点中的最近点对的距离; 这里的距离定义为不同类型的点之间的距离; [ ...

随机推荐

  1. iOS如何获取网络图片(三)有沙盒的

    沙盒 沙盒简介 默认情况下,每个沙盒含有3个文件夹:Documents, Library 和 tmp.因为应用的沙盒机制,应用只能在几个目录下读写文件 Documents:苹果建议将程序中建立的或在程 ...

  2. 【Android】用MediaRecorder录制视频太短崩的问题

    具体表现: 调用MediaRecorder的start()与stop()间隔不能小于1秒(有时候大于1秒也崩),否则必崩. 错误信息: java.lang.RuntimeException: stop ...

  3. 百度地图TILE算法

    Creating primary keyvar LLBAND2 = [75, 60, 45, 30, 15, 0]; var LL2MC2 = [[-.0015702102444, 111320.70 ...

  4. 在Eclipse上使用Maven

    Maven安装 去官网下载Maven,如下链接: http://maven.apache.org/download.cgi# 选择下载Binary zip archive 解压到本地,安装Maven前 ...

  5. Linux Found a swap file by the name filename

    在Linux中使用vi命令编辑mysql_backup.sh时遇到下面提示信息 E325: ATTENTION Found a swap file by the name ".mysql_b ...

  6. hibernate总记录数查询和分页查询

    //参考代码 //第一种方法: String hql = "select count(*) from User as user"; Integer count = (Integer ...

  7. SQLServer复合查询条件(AND,OR,NOT)对NULL值的处理方法

    在SQL的3值逻辑下,一个查询条件可以产生以下三种情况:TRUE,FALSE,NULL.只有那些满足WHERE子句的值是TRUE的记录才出现在结果表中. NULL值影响查询条件的结果,并且结果很微妙. ...

  8. 烂泥:yum的使用及配置

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近由于服务器需求,需要在公司内网搭建内网yum源. 搭建内网yum源需要分以下几个步骤,如下: 1. yum是什么 2. repo文件是什么 3. r ...

  9. C语言基本类型之long long int

    大家都知道int在linux系统下默认是占4个字节,数值表示范围是:-2147483648~2147483647.即使是无符号unsigned int类型表示范围:0-4294967295,大约42亿 ...

  10. Linux screen 命令

    简单的来说 在screen里面敲的命令都是在后台的,所以不需要想bg那样,ctrl+z在bg把后台服务运行起来.而且下次可以直接进去screen作业的后台界面,可以看到我们过去敲的命令记录,即使你的C ...