最近点对问题

[Input Example]

2

4

1 1 5 5 5 7 10 10

15

-15 41 50 47 10 54 71 -57 35 -64 27 -70 -88 77 48 83 8 90 69 -96 29 -3 89 -9 -50 19 6 26 66 32

[Output Example]

2 3

5 6

1.分治

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 10000
#define MAX 0x7FFFFFFF
int num;

typedef struct _STAR STAR;
struct _STAR{
    int x;
    int y;
    int index;
};

STAR star[N+1];
STAR tempStar[N+1];
int result[2];
int minDis;

int comp(const void *a, const void *b)
{
    STAR *stara=(STAR *)a;
    STAR *starb=(STAR *)b;

    if(stara->x<starb->x) return -1;
    else if(stara->x>starb->x) return 1;
    else {
        if(stara->y<starb->y) return -1;
        else if(stara->y>starb->y) return 1;
        else return 0;
    }
}

int compy(const void *a, const void *b)
{
    STAR *stara=(STAR *)a;
    STAR *starb=(STAR *)b;

    if(stara->y<starb->y) return -1;
    else if(stara->y>starb->y) return 1;
    else return 0;
}

int min(int a, int b)
{
    return a<b?a:b;
}

int max(int a, int b)
{
    return a>b?a:b;
}

int dis(int left,int right, STAR *star)
{
    return (star[left].x-star[right].x)*(star[left].x-star[right].x)+(star[left].y-star[right].y)*(star[left].y-star[right].y);
}

int findStar(int left, int right, int *starX, int *starY)
{
    int d=MAX;

    if(left==right) {
        return MAX;
    }

    if(left+1==right) {
        *starX=min(star[left].index,star[right].index);
        *starY=max(star[left].index,star[right].index);    
        d=dis(left,right,star);
        return d;
    }

    int mid=left+((right-left)>>1);

    int d1=findStar(left,mid,starX,starY);

    int tempResult[2];

    int d2=findStar(mid+1,right,&tempResult[0],&tempResult[1]);

    if(d1<d2) {
        d=d1;
    } else if(d1>d2){
        d=d2;
        *starX=tempResult[0];
        *starY=tempResult[1];
    } else if(d1==d2){
        d=d1;
        if(*starX>tempResult[0]) {
            *starX=tempResult[0];
            *starY=tempResult[1];
        } else if(*starX==tempResult[0]) {
            if(*starY>tempResult[1]) {
                *starY=tempResult[1];
            }
        }
    }

    int i=0,j=0,k=0;
    for(i=left;i<=right;i++)
    {
        if(abs(star[i].x-star[mid].x)<=d) {
            tempStar[k]=star[i];
            k++;
        }
    }
    qsort(tempStar,k,sizeof(tempStar[0]),compy);

    for(i=0;i<k;i++)
    {
        for(j=i+1;j<k&&(tempStar[j].y-tempStar[i].y)<d;j++)
        {
            int d3=dis(i,j,tempStar);
            if(d3<d){
                d=d3;
                *starX=min(tempStar[i].index,tempStar[j].index);
                *starY=max(tempStar[i].index,tempStar[j].index);
            } else if(d3==d) {
                if(*starX>min(tempStar[i].index,tempStar[j].index)) {
                    *starX=min(tempStar[i].index,tempStar[j].index);
                    *starY=max(tempStar[i].index,tempStar[j].index);
                } else if(*starX==min(tempStar[i].index,tempStar[j].index)) {
                    if(*starY>max(tempStar[i].index,tempStar[j].index)) {
                        *starY=max(tempStar[i].index,tempStar[j].index);
                    }
                }
            }
        }
    }

    return d;
}

int main(void)
{
    int tc, T;
    
    //

    setbuf(stdout, NULL);

    scanf("%d", &T);
    for(tc = 0; tc < T; tc++)
    {
        scanf("%d", &num);

        memset(star,0,sizeof(star));
        memset(tempStar,0,sizeof(tempStar));
        memset(result,0,sizeof(result));

        int i;
        for(i=1;i<=num;i++)
        {
            scanf("%d", &star[i].x);
            scanf("%d", &star[i].y);
            star[i].index=i;
        }

        qsort(star+1,num,sizeof(star[0]),comp);

        minDis=findStar(1,num,&result[0],&result[1]);

        printf("%d %d
",result[0],result[1]);
        // Print the answer to standard output(screen).
    }

    return 0;//Your program should return 0 on normal termination.
}

2.简化问题:最近点对必然是投影在x,y上连续的点

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 10000
#define MAX 0x7FFFFFFF

int num;

typedef struct _STAR STAR;
struct _STAR{
    int x;
    int y;
    int index;
};

STAR star[N+1];

int result[2];
int minDis;

int compX(const void *a, const void *b)
{
    STAR *stara=(STAR *)a;
    STAR *starb=(STAR *)b;

    if(stara->x<starb->x) return -1;
    else if(stara->x>starb->x) return 1;
    else {
        if(stara->y<starb->y) return -1;
        else if(stara->y>starb->y) return 1;
        else return 0;
    }
}

int compY(const void *a, const void *b)
{
    STAR *stara=(STAR *)a;
    STAR *starb=(STAR *)b;

    if(stara->y<starb->y) return -1;
    else if(stara->y>starb->y) return 1;
    else {
        if(stara->x<starb->x) return -1;
        else if(stara->x>starb->x) return 1;
        else return 0;
    }
}

int min(int a, int b)
{
    return a<b?a:b;
}

int max(int a, int b)
{
    return a>b?a:b;
}

int dis(int left,int right)
{
    return (star[left].x-star[right].x)*(star[left].x-star[right].x)+(star[left].y-star[right].y)*(star[left].y-star[right].y);
}


void findStar()
{ 
    int i;
    for(i=1;i<=num-1;i++) {
        int tempDis=dis(i,i+1);    
        int minIndex=min(star[i].index,star[i+1].index);
        int maxIndex=max(star[i].index,star[i+1].index);
        if(tempDis<minDis) {
            minDis=tempDis;
            result[0]=minIndex;
            result[1]=maxIndex;
        } else if(tempDis==minDis) {
            minDis=tempDis;
            if(result[0]>minIndex) {
                result[0]=minIndex;
                result[1]=maxIndex;
            } else if(result[0]==minIndex) {
                if(result[1]>maxIndex) {
                    result[1]=maxIndex;
                }
            }
        }
    }
    
}
int main(void)
{
    int tc, T;

    //

    setbuf(stdout, NULL);

    scanf("%d", &T);
    for(tc = 0; tc < T; tc++)
    {
        memset(result,0,sizeof(result));
        memset(star,0,sizeof(star));
        minDis = MAX;

        scanf("%d", &num);

        int i;
        for(i=1;i<=num;i++) {
            scanf("%d", &star[i].x);
            scanf("%d", &star[i].y);
            star[i].index=i;
        }

        qsort(star+1, num, sizeof(star[0]), compX);
        findStar();
        
        qsort(star+1, num, sizeof(star[0]), compY);
        findStar();
        
        printf("%d %d
",result[0],result[1]);
    }
    return 0;//Your program should return 0 on normal termination.
}
原文地址:https://www.cnblogs.com/mr-redrum/p/3573882.html