poj3714 Raid

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.

二分求平面最近点对。
按x排序后二分求解。
在合并子问题时,只需考虑横跨左右的答案。
取出所有与分界点x坐标之差不超过左右子问题最小值ans的点,只有这些才是可能解。
将这些点按y排序。
对于每个点,只与和他y坐标之差不超过ans的点计算。
可以证明,对于每个点,这样的点有常数多个【具体而言不超过6个】。
因为排过序,所以这一步可以O(n)解决。
有T(n)=2T(n/2)+O(nlogn)。
于是T(n)=O(n(logn)^2)。
因为要求两个点必须是不同集合的,所以计算距离时加上一个判断条件,如果属于相同集合返回无穷大即可。

#include
#include
#include
#include
using namespace std;
const double oo=1e50;
int n;
double ab(double x)
{
    return x>0?x:-x;
}
struct node
{
    double x,y;
    bool bel;
}a[200010],temp[200010];
bool cx(const node &a,const node &b)
{
    return a.xbool cy(const node &a,const node &b)
{
    return a.ydouble min(double x,double y)
{
    return xdouble dis(node p,node q)
{
    if (p.bel==q.bel) return oo;
    return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
double make(int l,int r)
{
    if (l==r) return oo;
    int m=(l+r)/2,i,j,k,ll,rr,p,q,x,y,z,cnt=0;
    double ans=min(make(l,m),make(m+1,r));
    for (i=l;i<=r;i++)
      if (ab(a[i].x-a[m].x)<=ans)
        temp[++cnt]=a[i];
    sort(temp+1,temp+cnt+1,cy);
    for (i=1;i<=cnt;i++)
      for (j=i+1;j<=cnt;j++)
      {
        if (temp[j].y-temp[i].y>ans) break;
        ans=min(ans,dis(temp[i],temp[j]));
      }
    return ans;
}
int main()
{
    int i,j,k,T;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
        {
            scanf("%lf%lf",&a[i].x,&a[i].y);
            a[i].bel=0;
        }
        for (i=1;i<=n;i++)
        {
            scanf("%lf%lf",&a[i+n].x,&a[i+n].y);
            a[i+n].bel=1;
        }
        sort(a+1,a+2*n+1,cx);
        printf("%.3f\n",make(1,2*n));
    }
}

你可能感兴趣的:(其他算法,poj)