Minimum Sum 平面最近點對

You are given a set of n vectors on a plane. For each vector you are allowed to multiply any of its coordinates by -1. Thus, each vector vi = (xi, yi) can be transformed into one of the following four vectors:

  • vi1 = (xi, yi),
  • vi2 = ( - xi, yi),
  • vi3 = (xi,  - yi),
  • vi4 = ( - xi,  - yi).

You should find two vectors from the set and determine which of their coordinates should be multiplied by -1 so that the absolute value of the sum of the resulting vectors was minimally possible. More formally, you should choose two vectorsvivj (1 ≤ i, j ≤ n, i ≠ j) and two numbers k1k2 (1 ≤ k1, k2 ≤ 4), so that the value of the expression |vik1 + vjk2| were minimum.

Input

The first line contains a single integer n (2 ≤ n ≤ 105). Then n lines contain vectors as pairs of integers "xi yi" ( - 10000 ≤ xi, yi ≤ 10000), one pair per line.

Output

Print on the first line four space-separated numbers "i k1 j k2" — the answer to the problem. If there are several variants the absolute value of whose sums is minimum, you can print any of them.

Sample test(s)
input
5
-8 -3
-9 -6
-4 9
5 3
9 3
output
5 1 1 1
input
5
-3 -8
-9 10
-9 0
-9 -2
-6 5
output
4 4 3 3
Note

A sum of two vectors v = (xv, yv) and u = (xu, yu) is vector s = v + u = (xv + xu, yv + yu).

An absolute value of vector v = (x, y) is number .

In the second sample there are several valid answers, such as:

(3 1 4 2), (3 1 4 4), (3 4 4 1), (3 4 4 3), (4 1 3 2), (4 1 3 4), (4 2 3 1).


//


#include<iostream>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=200000;
const int inf=(1<<30);
struct Point
{
    double x,y;//座標
    int k;
    int id;//標號
};
int n;//點數
Point a[maxn];
int cx,cy;//最近點對
int k1,k2;
double cmin;
double dis(Point h,Point k)
{
    return sqrt((h.x-k.x)*(h.x-k.x)+(h.y-k.y)*(h.y-k.y));
}
bool cmp(Point h,Point k)
{
    if(h.x!=k.x) return h.x<k.x;
    return h.y<k.y;
}
int y[maxn],len;
bool cmp2(int i,int j)
{
    return a[i].y<a[j].y;
}
void solve(int l,int r)
{
    if(l==r) return ;
    if(l==r-1)
    {
        double tmp=dis(a[l],a[r]);
        if(tmp<cmin) cmin=tmp,cx=a[l].id,k1=a[l].k,cy=a[r].id,k2=a[r].k;
    }
    if(l==r-2)
    {
        double l1=dis(a[l],a[l+1]);
        double l2=dis(a[l+1],a[l+2]);
        double l3=dis(a[l],a[l+2]);
        if(l1<l2&&l1<l3)
        {
            if(l1<cmin) cmin=l1,cx=a[l].id,k1=a[l].k,cy=a[l+1].id,k2=a[l+1].k;
        }
        if(l2<l1&&l2<l3)
        {
            if(l2<cmin) cmin=l2,cx=a[l+1].id,k1=a[l+1].k,cy=a[l+2].id,k2=a[l+2].k;
        }
        if(l3<cmin) cmin=l3,cx=a[l].id,k1=a[l].k,cy=a[l+2].id,k2=a[l+2].k;
    }
    int mid=(l+r)>>1;
    solve(l,mid);solve(mid+1,r);
    len=0;
    for(int i=l;i<=r;i++)
    {
        if(fabs(a[i].x-a[mid].x)<cmin)
        {
            y[len++]=i;
        }
    }
    sort(y,y+len,cmp2);
    for(int i=0;i<len;i++)
    {
        for(int j=i+1,cnt=1;j<len&&cnt<=7;j++,cnt++)
        {
            double tmp=dis(a[y[i]],a[y[j]]);
            if(tmp<cmin)
            {
                cmin=tmp,cx=a[y[i]].id,k1=a[y[i]].k,cy=a[y[j]].id,k2=a[y[j]].k;
            }
        }
    }
}
int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    while(scanf("%d",&n)==1)
    {
        cmin=inf;
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&a[i].x,&a[i].y);
            if(a[i].x>=0&&a[i].y>=0) a[i].k=1;
            else if(a[i].x<0&&a[i].y<0) a[i].k=4;
            else if(a[i].x<0) a[i].k=2;
            else a[i].k=3;
            a[i].x=fabs(a[i].x);a[i].y=fabs(a[i].y);
            a[i].id=i+1;
        }
        sort(a,a+n,cmp);
        solve(0,n-1);
        printf("%d %d %d %d\n",cx,k1,cy,5-k2);
        //printf("%d %d/n",min(cx,cy),max(cx,cy));
        //printf("%.3lf\n",cmin);
    }
    return 0;
}



發佈了743 篇原創文章 · 獲贊 5 · 訪問量 69萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章