最近对问题(蛮力法、分治法)

输入:点对个数, 点对的数值

输出:点对之间的最短距离

一、蛮力法

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define MAX 99999
using namespace std;
double closestPoints(double x[],double y[],int n)
{
    double x1,x2,y1,y2;                      //记录下标
    double dist,minDist=MAX;
    for(int i=0; i<n; i++)
        for(int j=i+1; j<n; j++)
        {
            dist=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);       //计算距离
            if(dist<minDist)
            {
                minDist=dist;
                x1=x[i];
                y1=y[i];
                x2=x[j];
                y2=y[j];
            }
        }
    cout<<"最近的点对为:("<<x1<<","<<y1<<")-("<<x2<<","<<y2<<")"<<endl;      //输出坐标
    return minDist;
}

int main()
{
    double x[100],y[100];
    double minDist;
    int n;
    cout<<"输入点的个数:\n";
    cin>>n;
    cout<<"输入点集的坐标:\n";
    for(int i=0; i<n; i++)
        cin>>x[i]>>y[i];
    minDist=closestPoints(x,y,n);
    cout<<"其距离为:"<<sqrt(minDist);
    return 0;
}

二、分治法

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define n 10
using namespace std;
struct point
{
    int x,y;
};

bool cmp(point a,point b)           //按y升排序辅助函数
{
    return a.y<b.y;
}
bool cmp2(point a,point b)           //按x升排序辅助函数
{
    return a.x<b.x;
}

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

double Closest(point s[],int low,int high)
{
    double d1,d2,d3,d;
    int mid,i,j,index;
    point p[n];
    if(high-low==1)
        return Distance(s[low],s[high]);
    if(high-low==2)
    {
        d1=Distance(s[low],s[low+1]);
        d2=Distance(s[low+1],s[high]);
        d3=Distance(s[low],s[high]);
        if((d1<d2)&&(d1<d3))
            return d1;
        else if(d2<d3)
            return d2;
        else
            return d3;
    }
    mid=(low+high)/2;
    d1=Closest(s,low,mid);
    d2=Closest(s,mid+1,high);
    if(d1<=d2)
        d=d1;
    else
        d=d2;
    index=0;
    for(i=mid;(i>=low)&&(s[mid].x-s[i].x<d);i--)
        p[index++]=s[i];
    for(i=mid+1;(i<=high)&&(s[i].x-s[mid].x<d);i++)
        p[index++]=s[i];
    sort(p,p+index,cmp);
    for(i=0;i<index;i++)
    {
        for(j=i+1;j<index;j++)
        {
            if(p[j].y-p[i].y>=d)
                break;
            else
            {
                d3=Distance(p[i],p[j]);
                if(d3<d)
                    d=d3;
            }
        }
    }
    return d;
}

int main()
{
    point p[10];            //设定点的集合
    int m;
    double minDist;
    cout<<"输入点的个数:\n";      //输入点的个数
    cin>>m;
    cout<<"输入点集:(x,y)\n";
    for(int i=0; i<m; i++)
        cin>>p[i].x>>p[i].y;
    sort(p,p+m,cmp2);      //对输入的点先排序
    point index[2];
    minDist=Closest(p,0,n-1);
    cout<<"最小距离为:"<<minDist;      //输出点对的最小问题
    return 0;
}

修改后的代码:增加了一个数组用来输出最短点对

/*分治法*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct point            //点结构
{
    double x,y;
};
double Distance(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(point a,point b)           //按y升排序辅助函数
{
    return a.y<b.y;
}
bool cmp2(point a,point b)           //按x升排序辅助函数
{
    return a.x<b.x;
}
double Closest(point s[],int low,int high,point rec[])
{
    double d1,d2,d3,d;
    int mid,i,j,index;
    double x1,y1,x2,y2;         //记录点对的位置
    point P[high-low+1],temp1[2],temp2[2],temp3[2];         //辅助空间
    if(high-low==1)              //两个点的情况
    {
        rec[0].x=s[low].x;
        rec[0].y=s[low].y;
        rec[1].x=s[high].x;
        rec[1].y=s[high].y;
        return Distance(s[low],s[high]);
    }
    if(high-low==2)             //三个点的情况
    {
        d1=Distance(s[low],s[low+1]);
        d2=Distance(s[low+1],s[high]);
        d3=Distance(s[low],s[high]);
        if((d1<d2)&&(d1<d3))
        {
            rec[0].x=s[low].x;
            rec[0].y=s[low].y;
            rec[1].x=s[low+1].x;
            rec[1].y=s[low+1].y;
            return d1;
        }
        else if(d2<d3)
        {
            rec[0].x=s[low+1].x;
            rec[0].y=s[low+1].y;
            rec[1].x=s[high].x;
            rec[1].y=s[high].y;
            return d2;
        }
        else
        {
            rec[0].x=s[low].x;
            rec[0].y=s[low].y;
            rec[1].x=s[high].x;
            rec[1].y=s[high].y;
            return d3;
        }
    }
    mid=(low+high)/2;       //其他情况递归
    d1=Closest(s,low,mid,rec);
    temp1[0]=rec[0];
    temp1[1]=rec[1];
    d2=Closest(s,mid+1,high,rec);
    temp2[0]=rec[0];
    temp2[1]=rec[1];
    if(d1<d2)
    {
        d=d1;
        rec[0]=temp1[0];
        rec[1]=temp1[1];
    }
    else
    {
        d=d2;
        rec[0]=temp2[0];
        rec[1]=temp2[1];
    }
    index=0;
    for(i=mid; (i>=low)&&((s[mid].x-s[i].x)<d); i--)    //点集合p1
        P[index++]=s[i];
    for(i=mid+1; (i<=high)&&((s[i].x-s[mid].x)<d); i++)    //点集合p2
        P[index++]=s[i];
    sort(P,P+index,cmp);                    //升序排列
    for(i=0; i<index; i++)
    {
        for(j=j+1; j<index; i++)
        {
            if((P[j].y-P[i].y)>=d)
                break;
            else
            {
                d3=Distance(P[i],P[j]);
                if(d3<d)
                {
                    rec[0].x=P[i].x;
                    rec[0].y=P[i].y;
                    rec[1].x=P[j].x;
                    rec[1].y=P[j].y;
                    d=d3;
                }
            }
        }
    }
    return d;
}
int main()
{
    point p[10];            //设定点的集合
    int n;
    double minDist;
    cout<<"输入点的个数:\n";      //输入点的个数
    cin>>n;
    cout<<"输入点集:(x,y)\n";
    for(int i=0; i<n; i++)
        cin>>p[i].x>>p[i].y;
    sort(p,p+n,cmp2);      //对输入的点先排序
    point index[2];
    minDist=Closest(p,0,n-1,index);
    cout<<"最小距离点对为:("<<index[0].x<<","<<index[0].y<<")-("<<index[1].x<<","<<index[1].y<<")\n";
    cout<<"最小距离为:"<<minDist;      //输出点对的最小问题
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40513088/article/details/85317737
今日推荐