Raid
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 10625   Accepted: 3192

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.  

Output

For each test case output the minimum distance with precision of three decimal placed in a separate line.

Sample Input

2
4
0 0
0 1
1 0
1 1
2 2
2 3
3 2
3 3
4
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0

Sample Output

1.414
0.000

Source

______________________________

平面最近点对,先按照x排序。然后二分。合并两个子问题时,先取两个子问题的最小值x,然后把切分的位置左右的点找出来(在x以内的)。 
然后把这些点按照y排序。然后枚举。显然是单调的,如果超过就跳出(强力剪枝)。注意计算距离时,如果两个点在同一个子集里,返回无限大的值。

________________分析懒得写了,直接搬运隔壁Orion_Rigel的______________

WA了好多次,最后试了一下把读入的坐标从int改成double就AC了

之后试了试另外一种,两个集合分开算的写法,不幸WA。嘛,不管了。

先放AC的代码:

 #include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double INF=;
const int mxn=;
struct node{
double x,y;//坐标也可能是实数
int f;
}a[mxn];
int pt[mxn];
double ans;
int n;
int cmpx(node a,node b){
return a.x<b.x;
}
int cmpy(int b,int c){
return a[b].y<a[c].y;
}
double dist(node a,node b){
if(a.f==b.f)return INF;//如果是同集合的点,返回INF
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double mindis(int l,int r){//求最小距离
if(l==r)return INF;
if(r-l==) return dist(a[r],a[l]);
double res=INF;
int mid=(l+r)>>;
res=mindis(l,mid);
res=min(res,mindis(mid+,r));//分治
int cnt=;
int i,j;
for(i=l;i<=r;++i)//剪枝,只从可能更优的点里找
if(fabs(a[i].x-a[mid].x)<=res)pt[cnt++]=i;
sort(pt,pt+cnt,cmpy);
double mind=INF;
for(i=;i<cnt;i++){
for(j=i+;j<cnt;j++){
if(fabs(a[pt[i]].y-a[pt[j]].y)>=res)break;
if((mind=dist(a[pt[i]],a[pt[j]]))<res)res=mind;
}
}
return res;
}
int main(){
int T;
scanf("%d",&T);
int i,j;
while(T--){
scanf("%d",&n);
int x,y;
for(i=;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y),a[i].f=;
int nn=n*;
for(i=n+;i<=nn;i++)scanf("%lf%lf",&a[i].x,&a[i].y),a[i].f=;
sort(a+,a+nn+,cmpx);
ans=mindis(,nn);
printf("%.3lf\n",ans);
}
return ;
}

下面是WA的算法,路过的大神求指点……

 #include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int mxn=;
struct node{
double x,y;
}s[mxn],a[mxn];
int cmpx(node a,node b){
return a.x<b.x;
}
int cmpy(node a,node b){
return a.y<b.y;
}
double mans;
int n;
int mxx=;
inline double dist(int x1,int y1,int x2,int y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void cl(int l,int r){
if(l>=r-)return;
int mid=(l+r)/;
cl(l,mid);
cl(mid,r);
if(r-l>mans)return;
int i,j;
int dx=mid-mans;
int dx2=mid+mans;
for(i=;i<=n;i++){
if(s[i].x<dx)continue;
if(s[i].x>mid)break;
for(j=;a[j].x<dx2 && j<=n;j++){
if(a[j].x<dx)continue;
if(a[j].y<s[i].y-mans || a[j].y>s[i].y+mans)continue;
mans=min(mans,dist(s[i].x,s[i].y,a[j].x,a[j].y));
}
}
return;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int i,j;
for(i=;i<=n;i++){
scanf("%lf%lf",&s[i].x,&s[i].y);
}
for(i=;i<=n;i++){
scanf("%lf%lf",&a[i].x,&a[i].y);
}
sort(s+,s+n+,cmpx);
sort(a+,a+n+,cmpx);
mans=;
cl(,*n);
printf("%.3lf\n",mans);
}
}

POJ3714 Raid的更多相关文章

  1. poj3714 Raid(分治求平面最近点对)

    题目链接:https://vjudge.net/problem/POJ-3714 题意:给定两个点集,求最短距离. 思路:在平面最近点对基础上加了个条件,我么不访用f做标记,集合1的f为1,集合2的f ...

  2. POJ-3714 Raid 平面最近点对

    题目链接:http://poj.org/problem?id=3714 分治算法修改该为两个点集的情况就可以了,加一个标记... //STATUS:C++_AC_2094MS_4880KB #incl ...

  3. POJ3714 Raid 分治/K-D Tree

    VJ传送门 简要题意:给出两个大小均为\(N\)的点集\(A,B\),试在\(A\)中选择一个点,在\(B\)中选择一个点,使得它们在所有可能的选择方案中欧几里得距离最小,求出这个距离 下面给出的两种 ...

  4. 【poj3714】 Raid

    http://poj.org/problem?id=3714 (题目链接) 现在才搞平面最近点对..感觉有点尴尬 题意 给出平面上两组点,每组n个,求两组点之间最短距离 Solution1 平面最近点 ...

  5. 【POJ3714】Raid:平面最近点对

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

  6. $Poj3714/AcWing\ Raid$ 分治/平面最近点对

    $AcWing$ $Sol$ 平面最近点对板子题,注意要求的是两种不同的点之间的距离. $Code$ #include<bits/stdc++.h> #define il inline # ...

  7. 『Raid 平面最近点对』

    平面最近点对 平面最近点对算是一个经典的问题了,虽然谈不上是什么专门的算法,但是拿出问题模型好好分析一个是有必要的. 给定\(n\)个二元组\((x,y)\),代表同一平面内的\(n\)个点的坐标,求 ...

  8. 一张“神图”看懂单机/集群/热备/磁盘阵列(RAID)

    单机部署(stand-alone):只有一个饮水机提供服务,服务只部署一份 集群部署(cluster):有多个饮水机同时提供服务,服务冗余部署,每个冗余的服务都对外提供服务,一个服务挂掉时依然可用 热 ...

  9. 什么是RAID?RAID有什么用?RAID原理

    什么是RAID 硬盘是个很脆弱的东西,它经常会坏掉.所以,为了保证服务器可靠耐用,硬盘必须时时刻刻保持可用.所以有了RAID这个东西.它的目的是将好几个硬盘合并在一起,就算硬盘坏了一个,剩下还有好几个 ...

随机推荐

  1. java 20 -2 递归之找特定目录下的特定格式文件

    /* 需求:把C:\Users\Administrator\Desktop\记录目录下所有以.java结尾的文件的绝对路径输出到控制台 分析: A:封装该目录 B:获取该目录下的所有文件或文件夹的Fi ...

  2. js的nextSibling,属性兼容IE和FF等浏览器

    Firefox中 空白字符,比如回车,空格等也算作一个Node 就是firstChild,nextsbiling这两个.下面给出函数吧.还是代码比较说明问题代码都是网上来的.不过要注意的是,getNe ...

  3. NOI 1.7编程基础之字符串(35题)

    01:统计数字字符个数 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 输入一行字符,统计出其中数字字符的个数. 输入 一行字符串,总长度不超过255. 输出 ...

  4. python学习三

    输入与输出 print()在括号中加上字符串,就可以向屏幕上输出指定的文字. >>>print('hello world')hello world print()函数也可以接受多个字 ...

  5. MySQL基础 - 内置函数

    Concat() 用于连接字段,一般DBMS使用+或者||. ex: 注意:上图中新检索出来的列名为'CONCAT(id, '->', name)'(实际上没有列名),这样虽然不影响在MySQL ...

  6. Android开发探秘之三:利用jsoup解析HTML页面

    这节主要是讲解jsoup解析HTML页面.由于在android开发过程中,不可避免的涉及到web页面的抓取,解析,展示等等,所以,在这里我主要展示下利用jsoup jar包来抓取cnbeta.com网 ...

  7. LeetCode 笔记23 Best Time to Buy and Sell Stock III

    Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of ...

  8. google map api v2的使用详细过程,图文并茂(原创)

    上一篇中说到怎么获取key,下面来介绍怎么使用key来显示google地图 步骤1:eclipse上打开android SDK Manager,安装google play services. 步骤2: ...

  9. python实现简易数据库之三——join多表连接和group by分组

    上一篇里面我们实现了单表查询和top N查询,这一篇我们来讲述如何实现多表连接和group by分组. 一.多表连接 多表连接的时间是数据库一个非常耗时的操作,因为连接的时间复杂度是M*N(M,N是要 ...

  10. 秒杀9种排序算法(JavaScript版)

    一:你必须知道的 1> JS原型 2> 排序中的有序区和无序区 3> 二叉树的基本知识 如果你不知道上面三个东西,还是去复习一下吧,否则,看下面的东西有点吃力. 二:封装丑陋的原型方 ...