最近点对及距离

 距离上次写算法题目已经有半个月了吧。从20号回学校参加毕业典礼,和舍友,和同学疯狂了十天。很高兴,也很伤感。终于,我也本科毕业了。最终,分离的那一天还是要到来

的,我最舍不得的是和海哥还有小强的感情,再也听不到他们的嬉戏打闹的声音,再也听不到他们的狂叫,再也看不到他们疯疯癫癫的样子。现在回想起我们一起的点点滴滴,我的眼泪又忍不住要往下滴了。在这我只想偷偷的告诉你们,我想你们了。

  现在我们都开始了自己新的生活了,虽然说我们不能活在过去,但是我们也要相离莫相忘。一定要彼此挂念!

题目描述:

  给定平面N个点的坐标,找出距离最近的点对以及最近的距离。

解题思路:

  用分治的方法来解决。按x轴排序,然后找中间的点, 把所有点分成左右两部分,递归求左右两边的最短距离。当然还要考虑左边和右边点的距离。

  好了,关于问题的描述网上有很多很多,我也懒得写了,也写不了那么好。我也是先看了别人的分析,才写出来的。

代码:

//求平面内最近的两点及距离

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

typedef struct{
    int x;
    int y;
}POINT;

//记录最近点对以及距离
typedef struct{
    int a;
    int b;
    double dMinDist;
}MinestPoint;

POINT pointAll[100];
POINT pointY[100];
MinestPoint nMinestPoint;


MinestPoint Min(MinestPoint a, MinestPoint b)
{
    if (a.dMinDist < b.dMinDist) return a;
    else return b;
}

//按x轴排序
int cmpX(const void *a, const void *b)
{
    POINT *p1,*p2;
    p1 = (POINT *)a; p2 = (POINT *)b;
    if (p1->x == p2->x) return p1->y - p2->y;
    return p1->x - p2->x;
}

//按y轴排序
int cmpY(const void *a, const void *b)
{
    POINT *p1,*p2;
    p1 = (POINT *)a; p2 = (POINT *)b;
    if (p1->y == p2->y) return p1->x - p2->x;
    return p1->y - p2->y;
}


int Input() 
{
    int i=0,n;
    FILE *fp;

    fp = fopen("in.txt","r");
    if (fp == NULL)
    {
        printf("fopen error.\n");
        return -1;
    }
    
    fscanf(fp,"%d",&n);
    while (i < n)
    {
        fscanf(fp,"%d%d",&pointAll[i].x,&pointAll[i].y);
        i++;
    }
    qsort(pointAll,n,sizeof(POINT),cmpX);

    for (i = 0; i < n; i++)
    {
        printf("(%d,%d) ",pointAll[i].x,pointAll[i].y);
    }
    printf("\n");
    return n;
}

double Dist(POINT a, POINT b)
{
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

MinestPoint DivideConque(int left, int right)
{
    int nMid,nCnt,i,j;
    double nDist;
    MinestPoint nMinLeft,nMinRight;
    
    if (left == right) 
    {
        if (1000 == nMinestPoint.dMinDist )
        {
            nMinestPoint.a = nMinestPoint.b = left;
        }
        return nMinestPoint;
    }
    if (left+1 == right)
    {
        nDist = Dist(pointAll[left],pointAll[right]);
        if ( nDist < nMinestPoint.dMinDist)
        {
            nMinestPoint.a = left;
            nMinestPoint.b = right;
            nMinestPoint.dMinDist = nDist;
        }
        return nMinestPoint;
    }
    
    nMid = (right + left)/2;
    nMinLeft = DivideConque(left,nMid);
    nMinRight = DivideConque(nMid+1,right);
    
    nMinestPoint = Min(nMinLeft,nMinRight);

    //选取在中线附近的点
    nCnt = 0;
    for (i = left; i <= right; i++)
    {
        if (pointAll[i].x <= pointAll[nMid].x + nMinestPoint.dMinDist &&
            pointAll[i].x >= pointAll[nMid].x - nMinestPoint.dMinDist)
        {
            pointY[nCnt++] = pointAll[i];
        }
    }

    qsort(pointY,nCnt,sizeof(POINT),cmpY);

    for (i = 0; i < nCnt; i++)
    {
        for (j = i + 1; j < nCnt; j++)
        {
            if (pointY[j].y - pointY[i].y > nMinestPoint.dMinDist)
                break;
            nDist = Dist(pointY[i],pointY[j]);
            if (nDist < nMinestPoint.dMinDist)
            {
                nMinestPoint.a = i;
                nMinestPoint.b = j;
                nMinestPoint.dMinDist = nDist;
            }
        }
    }
    return nMinestPoint;
}


int main()
{
    int n,a,b;
    nMinestPoint.dMinDist = 1000;  //假设1000为正无穷

    n = Input();
    DivideConque(0,n-1);
    a = nMinestPoint.a;
    b = nMinestPoint.b;
    
    printf("Minest Dist is:%f.\n",nMinestPoint.dMinDist);
    printf("the point a:(%d,%d),point b is:(%d,%d).\n",pointAll[a].x,pointAll[a].y,
        pointAll[b].x,pointAll[b].y);
    return 0;
}

2013/7/7 20:53

 

转载于:https://www.cnblogs.com/Jason-Damon/p/3176717.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值