zoukankan      html  css  js  c++  java
  • POJ3714 Raid

    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的代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const double INF=2000000001;
     8 const int mxn=200500;
     9 struct node{
    10     double x,y;//坐标也可能是实数 
    11     int f;
    12 }a[mxn];
    13 int pt[mxn];
    14 double ans;
    15 int n;
    16 int cmpx(node a,node b){
    17     return a.x<b.x;
    18 }
    19 int cmpy(int b,int c){
    20     return a[b].y<a[c].y;
    21 }
    22 double dist(node a,node b){
    23     if(a.f==b.f)return INF;//如果是同集合的点,返回INF 
    24     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    25 }
    26 double mindis(int l,int r){//求最小距离 
    27     if(l==r)return INF;
    28     if(r-l==1)    return dist(a[r],a[l]);
    29     double res=INF;
    30     int mid=(l+r)>>1;
    31     res=mindis(l,mid);
    32     res=min(res,mindis(mid+1,r));//分治 
    33     int cnt=0;
    34     int i,j;
    35     for(i=l;i<=r;++i)//剪枝,只从可能更优的点里找 
    36         if(fabs(a[i].x-a[mid].x)<=res)pt[cnt++]=i;
    37     sort(pt,pt+cnt,cmpy);
    38     double mind=INF;
    39     for(i=0;i<cnt;i++){
    40         for(j=i+1;j<cnt;j++){
    41             if(fabs(a[pt[i]].y-a[pt[j]].y)>=res)break;
    42             if((mind=dist(a[pt[i]],a[pt[j]]))<res)res=mind;
    43         }
    44     }
    45     return res;
    46 }
    47 int main(){
    48     int T;
    49     scanf("%d",&T);
    50     int i,j;
    51     while(T--){
    52         scanf("%d",&n);
    53         int x,y;
    54         for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y),a[i].f=0;
    55         int nn=n*2;
    56         for(i=n+1;i<=nn;i++)scanf("%lf%lf",&a[i].x,&a[i].y),a[i].f=1;
    57         sort(a+1,a+nn+1,cmpx);
    58         ans=mindis(1,nn);
    59         printf("%.3lf
    ",ans);
    60     }
    61     return 0;
    62 }

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

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int mxn=100500;
     8 struct node{
     9     double x,y;
    10 }s[mxn],a[mxn];
    11 int cmpx(node a,node b){
    12     return a.x<b.x;
    13 }
    14 int cmpy(node a,node b){
    15     return a.y<b.y;
    16 }
    17 double mans;
    18 int n;
    19 int mxx=0;
    20 inline double dist(int x1,int y1,int x2,int y2){
    21     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    22 }
    23 void cl(int l,int r){
    24     if(l>=r-1)return;
    25     int mid=(l+r)/2;
    26     cl(l,mid);
    27     cl(mid,r);
    28     if(r-l>mans)return;
    29     int i,j;
    30     int dx=mid-mans;
    31     int dx2=mid+mans;
    32     for(i=1;i<=n;i++){
    33         if(s[i].x<dx)continue;
    34         if(s[i].x>mid)break;
    35         for(j=1;a[j].x<dx2 && j<=n;j++){
    36             if(a[j].x<dx)continue;
    37             if(a[j].y<s[i].y-mans || a[j].y>s[i].y+mans)continue;
    38             mans=min(mans,dist(s[i].x,s[i].y,a[j].x,a[j].y));
    39         }
    40     }
    41     return;
    42 }
    43 int main(){
    44     int T;
    45     scanf("%d",&T);
    46     while(T--){
    47         scanf("%d",&n);
    48         int i,j;
    49         for(i=1;i<=n;i++){
    50             scanf("%lf%lf",&s[i].x,&s[i].y);
    51         }
    52         for(i=1;i<=n;i++){
    53             scanf("%lf%lf",&a[i].x,&a[i].y);
    54         }
    55         sort(s+1,s+n+1,cmpx);
    56         sort(a+1,a+n+1,cmpx);
    57         mans=1000000000;
    58         cl(0,2*n);
    59         printf("%.3lf
    ",mans);
    60     }
    61 }
    View Code
  • 相关阅读:
    Android 显示或隐藏标题栏进度条TitleProgressBar
    Android 利用Sharp样式设置文本框EditText圆角形状
    Android 中带有进度条效果的按钮(Button)
    Android 手势滑动,多点触摸放大缩小图片
    Android (Notification)消息推送机制
    Android AutoCompleteTextView控件实现类似百度搜索提示,限制输入数字长度
    Android 横向列表GridView 实现横向滚动
    Android 利用 AsyncTask 异步读取网络图片
    Android 各种功能代码收集
    Android 之 AlarmManager(定时器) 的介绍和使用
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/5639094.html
Copyright © 2011-2022 走看看