题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007

Quoit Design

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 42865    Accepted Submission(s): 11128

Problem Description
Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded.
In the field of Cyberground, the position of each toy is fixed, and the ring is carefully designed so it can only encircle one toy at a time. On the other hand, to make the game look more attractive, the ring is designed to have the largest radius. Given a configuration of the field, you are supposed to find the radius of such a ring.

Assume that all the toys are points on a plane. A point is encircled by the ring if the distance between the point and the center of the ring is strictly less than the radius of the ring. If two toys are placed at the same point, the radius of the ring is considered to be 0.

 
Input
The input consists of several test cases. For each case, the first line contains an integer N (2 <= N <= 100,000), the total number of toys in the field. Then N lines follow, each contains a pair of (x, y) which are the coordinates of a toy. The input is terminated by N = 0.
 
Output
For each test case, print in one line the radius of the ring required by the Cyberground manager, accurate up to 2 decimal places. 
 
Sample Input
2
0 0
1 1
2
1 1
1 1
3
-1.5 0
0 0
0 1.5
0
 
Sample Output
0.71
0.00
0.75
 
Author
CHEN, Yue
 

最近点对问题:

分治的思想,如果是大于3个点的时候,将所有的点按照x坐标(或者y坐标)排序,然后从中间线一份两半,分别求出左边的点的最近点距ldis,和右边点的最近点距rdis,那么问题就是要将两个部分的点合起来,令dis = min(rdis,ldis);那么中间如果想出现最近点对的时候必须要出现在中间线两侧距离为d的区域内,那么考虑区域内的左侧的点,与其产生最近点的点一定在坐标的右侧,那么为了不用枚举区域内右边所有的点,就要考虑对于每个点它如果要产生距离小于dis的对应点,肯定是在以它为圆心的dis为半径的园内,那么这个圆覆盖这个带状区域面积最大的情况就是圆心在分界线上的时候。如图

注意:在处理中间带的时候将带状区域内的点按照y坐标排序(如果之前是按照y排序的,则现在按照x坐标排序)那么因为右侧的任意两点之间的距离要大于等于dis所以要想极限情况,就是在这个圆区域内找等边三角形,因为从上到下处理的点,所以当前点的上方的点不在考虑,由于排序的时候是左右两边的点一起排序的所以要在当前点的编号向后处理7个点,如上图中划出的三个点,如果发现他们来自同一侧则不再处理

下面是模板代码:

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std; #define N 100005
const int L = -;
const int R = ;
struct Node{
int id;
double x;
double y;
};
Node num[N],cp[N]; //double Dis(Node a, Node b){
// return sqrt(pow((a.x - b.x),2.0)+pow((a.y-b.y),2.0));
//}
double Dis(Node a, Node b){
double x = a.x-b.x, y = a.y-b.y;
return sqrt(x*x+y*y);
} bool cmpx(Node a, Node b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x < b.x;
}
bool cmpy(Node a, Node b)
{
if(a.y==b.y) return a.x<b.x;
else return a.y<b.y;
}
double solve(int low, int high)
{
double dis;
int sum = high - low;
if(sum == ){ return ; }//只有一个数
else if(sum == ){//两个数
dis = Dis(num[low],num[high]);
}
else if(sum == ){//三个数
double tm1,tm2,tm3;
tm1 = Dis(num[low],num[low+]);
tm2 = Dis(num[low+],num[high]);
tm3 = Dis(num[low],num[high]);
dis = min(tm1,min(tm2,tm3));
}
else //大于三个数
{
double lmin,rmin,mmin;
int mid = (low+high)/;
int p = ;
int i, j;
lmin = solve(low,mid);
rmin = solve(mid+,high);
dis = min(lmin,rmin);
/**-----------------提出来会变快-----------------*/
double ldis = num[mid].x-dis;
double rdis = num[mid].x+dis;
for( i = low; i <= mid; i++) /**-----小于等于,不能是小于,因为下面标记 L R 了*/
{
if(num[i].x >= ldis)
{
cp[p].id = L;//标记为属于左边的部分
cp[p].x = num[i].x;
cp[p].y = num[i].y;
p++;
}
}
for( ; i <= high; i++)
{
if(num[i].x <= rdis)
{
cp[p].id = R;//标记为右边的点
cp[p].x = num[i].x;
cp[p].y = num[i].y;
p++;
}
}
sort(cp,cp+p,cmpy);
for( i = ; i < p; i++)
{
for( j = ; (j <= )&&(i+j)<p; j++)
{
if(cp[i].id != cp[i+j].id)//最小值可能出现在分界线不同的两边
{
mmin = Dis(cp[i],cp[i+j]);
if(mmin<dis)
dis = mmin;
}
}
}
}
return dis;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n!=)
{
double result = ;
for(int i = ; i < n; i++)
{
num[i].id = ;
scanf("%lf%lf",&num[i].x,&num[i].y);
}
sort(num,num+n,cmpx);
result = solve(,n-);
printf("%.2f\n",result/);
}
return ;
}

下面是一开始wa的代码:

对应的错误在上面代码中用用/** -------*标识

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 100005
const int L = -;
const int R = ;
struct Node{
int id;
double x;
double y;
};
Node num[N],cp[N]; double Dis(Node a, Node b){
return sqrt(pow((a.x - b.x),2.0)+pow((a.y-b.y),2.0));
} bool cmpx(Node a, Node b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x < b.x;
}
bool cmpy(Node a, Node b)
{
if(a.y==b.y) return a.x<b.x;
else return a.y<b.y;
} double solve(int low, int high)
{
double dis;
int sum = high - low;
if(sum == ){ return ; }//只有一个数
else if(sum == ){//两个数
dis = Dis(num[low],num[high]);
}
else if(sum == ){//三个数
double tm1,tm2,tm3;
tm1 = Dis(num[low],num[low+]);
tm2 = Dis(num[low+],num[high]);
tm3 = Dis(num[low],num[high]);
dis = min(tm1,min(tm2,tm3));
}
else //大于三个数
{
double lmin,rmin,mmin;
int mid = (low+high)/;
int p = ;
int i, j;
lmin = solve(low,mid);
rmin = solve(mid+,high);
dis = min(lmin,rmin);
for( i = low; i < mid; i++)
{
double ldis = num[mid].x - dis;
if(num[i].x >= ldis)
{
cp[p].id = L;//标记为属于左边的部分
cp[p].x = num[i].x;
cp[p].y = num[i].y;
p++;
}
}
for( ; i < high; i++)
{
double rdis = num[mid].x+dis;
if(num[i].x <= rdis)
{
cp[p].id = R;//标记为右边的点
cp[p].x = num[i].x;
cp[p].y = num[i].y;
p++;
}
}
sort(cp,cp+p,cmpy);
for( i = ; i < p; i++)
{
for( j = ; (j <= )&&(i+j)<p; j++)
{
if(cp[i].id != cp[i+j].id)//最小值可能出现在分界线不同的两边
{
mmin = Dis(cp[i],cp[i+j]);
if(mmin<dis)
dis = mmin;
}
}
}
}
return dis;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n!=)
{
double result = ;
for(int i = ; i < n; i++)
{
num[i].id = ;
scanf("%lf%lf",&num[i].x,&num[i].y);
}
sort(num,num+n,cmpx);
result = solve(,n-);
printf("%.2f\n",result/);
}
return ;
}

下面给出大神的模板代码:(虽然内容差不多,感觉一下代码风格)

 #include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 100007 using namespace std; struct Point
{
double x,y;
}pt[N];
int a[N]; int n; bool cmp(Point a, Point b)
{
if (a.x != b.x) return a.x < b.x;
else return a.y < b.y;
}
bool cmp_y(int id1, int id2){
return pt[id1].y < pt[id2].y;
}
double getDis(const Point &a, const Point &b)
{
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
double solve(int l, int r)
{
double ans = ;
if (r - l + <= )
{
if (r - l + == ) return ans;
ans = getDis(pt[l], pt[l + ]);
if (r - l + == ) return ans;
for (int i = l; i < r; ++i)
{
for (int j = i + ; j <= r; ++j)
{
ans = min(ans, getDis(pt[i],pt[j]));
}
}
return ans;
}
int m = (l + r) >> ;
double s1 = solve(l, m);
double s2 = solve(m + , r);
ans = min(s1,s2);
int k = ;
for (int i = m - ; i >= l && pt[m].x - pt[i].x <= ans; --i) a[k++] = i;
for (int i = m + ; i <= r && pt[i].x - pt[m].x <= ans; ++i) a[k++] = i;
sort(a, a + k, cmp_y);
for (int i = ; i < k; ++i)
{
for (int j = i + ; j < k && j <= i + ; ++j)
{
ans = min(ans, getDis(pt[a[i]], pt[a[j]]));
}
}
return ans;
}
int main()
{
while (~scanf("%d",&n))
{
if (!n) break;
for (int i = ; i < n; ++i) scanf("%lf%lf",&pt[i].x, &pt[i].y);
sort(pt, pt + n, cmp);
printf("%.2lf\n",solve(, n - )/2.0);
}
return ;
}

Quoit Design(最近点对+分治)的更多相关文章

  1. hdu 1007 Quoit Design (最近点对问题)

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  2. 杭电OJ——1007 Quoit Design(最近点对问题)

    Quoit Design Problem Description Have you ever played quoit in a playground? Quoit is a game in whic ...

  3. ZOJ2107 Quoit Design 最近点对

    ZOJ2107 给定10^5个点,求距离最近的点对的距离. O(n^2)的算法是显而易见的. 可以通过分治优化到O(nlogn) 代码很简单 #include<iostream> #inc ...

  4. HDU 1007 Quoit Design最近点对( 分治法)

    题意: 给出平面上的n个点,问任意点对之间的最短距离是多少? 思路: 先将所有点按照x坐标排序,用二分法将n个点一分为二个部分,递归下去直到剩下两或一个点.对于一个部分,左右部分的答案分别都知道,那么 ...

  5. HDU 1007 Quoit Design【计算几何/分治/最近点对】

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  6. ZOJ 2017 Quoit Design 经典分治!!! 最近点对问题

    Quoit Design Time Limit: 5 Seconds      Memory Limit: 32768 KB Have you ever played quoit in a playg ...

  7. hdu 1007 Quoit Design 分治求最近点对

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  8. HDU 1007 Quoit Design(经典最近点对问题)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1007 Quoit Design Time Limit: 10000/5000 MS (Java/Oth ...

  9. HDU1007 Quoit Design 【分治】

    Quoit Design Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

随机推荐

  1. Visual Studio Code 通过 Chrome插件Type Script断点调试Angular 2

    1. 下载Visual Studio Code (https://code.visualstudio.com/) 2. 安装插件Debugger for chrome 3. 确定tsconfig.js ...

  2. Run a task only once in (akka) cluster

    在stackOverflow网站上看到这一提问,下文是部分摘抄问题简述: Java cluster, run task only once We have a java process, which ...

  3. python 将文件夹内的图片转换成PDF

    import os import stringfrom PIL import Imagefrom reportlab.lib.pagesizes import A4, landscapefrom re ...

  4. UVALive 3716 DNA Regions

    题目大意:给定两个长度相等的字符串A和B,与一个百分比p%,求最长的.失配不超过p%的区间长度.O(nlogn). 题目比较简单套路,推推式子就好了. 记S[i]表示到下标i一共有多少个失配,就相当于 ...

  5. bzoj 4719: [Noip2016]天天爱跑步

    Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一 ...

  6. NET Framework 版本和依赖关系

    原文:https://docs.microsoft.com/zh-cn/dotnet/framework/migration-guide/versions-and-dependencies 每个版本的 ...

  7. Windows as a Service(2)—— 使用WSUS管理Windows10更新

    前言 在上一篇Windows as a Service(1)-- Windows 10服务分支中,我和大家分享了Windows 10三个服务分支CB/CBB/LTSB的概念及不同,从这篇文档开始,我将 ...

  8. 什么是AJAX? AJAX:”Asynchronous JavaScript and XML”中文意思:异步JavaScript和XML。

    指一种创建交互式网页应用的网页开发技术. AJAX并非缩写词,而是由Jesse James Gaiiett创造的名词. 不是指一种单一的技术,而是有机地利用了一系列相关的技术: web标准( Stan ...

  9. Error in library(DESeq2) : 不存在叫‘DESeq2’这个名字的程辑包

    Error in read.dcf(file.path(pkgname, "DESCRIPTION"), c("Package", "Type&quo ...

  10. js获取样式、currentStyle和getComputedStyle的兼容写法

    currentStyle获取计算后的样式,也叫当前样式.最终样式.优点:可以获取元素的最终样式,包括浏览器的默认值,而不像style只能获取行间样式,所以更常用到.注意:不能获取复合样式如backgr ...