最短点对

难点:如何测试。我的解决方式是:a,三种解法,看结果是否一致。b,小数据(100个点),人工排查。第一种方法,暴力法适合小数据。第二种方法:我的改进型。第三种方法:经典方法(分治法)。实验证明1000万数据时,我的算法有优势。
暴力算法,O(n2)。我的改进型要点:先对所有数据按Y排序。只比较y距离小于等于已知最小距离的点对。经典方法:按Y排序,分成两部分,递归调用。合并师只比较距离分界线不超过已知最小距离的点对。
实际证明500万数据以下,我的改进算法明显优于经典算法;1000万数据时,略强于经典算法。

 

核心代码:

double Dis(const CPT& pt1,const CPT& pt2)
{
    return sqrt((double) (pt1.x-pt2.x)*(pt1.x-pt2.x)+(pt1.y-pt2.y)*(pt1.y-pt2.y)+(pt1.z-pt2.z)*(pt1.z-pt2.z) );
}

void InitData(CPT* pts,int iNum)
{
    srand(time(NULL));

    for( int i = 0 ; i < iNum ; i++)
    {
        pts[i].x = rand()%10000;
        pts[i].y = rand()%10000;
        pts[i].z = rand()%10000;
    }
}

double Fun1(CPT* pts,const int iNum)
{
     double dMinDis = 10000*10000 ;
    for(int i = 0 ; i < iNum ; i++ )
        for( int j = i+1 ; j < iNum ; j++ )
        {
            const double d = Dis(pts[i] , pts[j]);
            if( d < dMinDis)
            {
                dMinDis = d ;
            }
        }
        return dMinDis;
}

class CCmpY
{
public:
    bool operator()(const CPT& pt1,const CPT& pt2)
    {
        return pt1.y < pt2.y ;
    }
};

double Fun2(CPT* pts,const int iNum)
{
    std::sort(pts,pts+iNum,CCmpY() );

    double dMinDis = 10000*10000 ;
    for(int i = 0 ; i < iNum ; i++ )
        for( int j = i+1 ; j < iNum ; j++ )
        {
            const double d = Dis(pts[i] , pts[j]);
            if( d < dMinDis)
            {
                dMinDis = d ;
            }
            if( abs(pts[i].y - pts[j].y )> dMinDis )
            {
                break;
            }
        }
        return dMinDis;
}

double Fun3(CPT* pts,const int iNum)
{
    std::sort(pts,pts+iNum,CCmpY() );

    if( iNum < 100 )
    {
        return Fun1(pts,iNum);
    }

    const int iMid = iNum/2 ;
    const double dMin1 = Fun3(pts,iMid);
    const double dMin2 = Fun3(pts+iMid,iNum-iMid);
    double dMinDis = min(dMin1,dMin2) ;
    for(int i = iMid-1 ; i >= 0 ; i-- )//左集合
    {
        if( abs(pts[i].y - pts[iMid].y ) > dMinDis )
        {
            break;
        }
        for( int j = iMid ; j < iNum ; j++ )//右集合
        {
            const double d = Dis(pts[i] , pts[j]);
            if( d < dMinDis)
            {
                dMinDis = d ;
            }
            if( abs(pts[i].y - pts[j].y )> dMinDis )
            {
                break;
            }
        }
    }
        return dMinDis;
}

 


可通过以下链接下载测试数据,exe,源码(VS2005,VC8)
https://pan.baidu.com/s/1QyQgtUvqtuH3n7TCLHxKtA

转载于:https://www.cnblogs.com/he-zhidan/p/10202274.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 必经点最短路径问题是指在给定的带权有向图中,找到一条从起点到终点的路径,该路径经过指定的必经点,并且路程最短。解决这个问题可以使用Dijkstra算法或者Floyd-Warshall算法。 首先,使用Matlab创建带权有向图的邻接矩阵,其中边的权值表示两个顶点之间的距离。接下来,使用Dijkstra算法来求出起点到所有顶点的最短路径。 在实现Dijkstra算法时,需要使用一个距离数组dist和一个路径数组path来保存最短路径的信息。距离数组dist初始化为无穷大,起点的距离设为0。路径数组path初始化为空。 然后,从起点开始,依次遍历所有顶点。对于当前遍历的顶点,遍历其相邻的顶点,如果经过当前顶点到达相邻顶点的距离比之前的路径短,就更新距离数组dist和路径数组path。重复遍历所有顶点,直到达到终点。 最后,根据路径数组path,可以找到起点到终点的最短路径,并且该路径经过指定的必经点。同时,根据距离数组dist,可以得到最短路径的长度。将路径和长度输出即可。 因此,通过Matlab中的邻接矩阵和Dijkstra算法,我们能够求解必经点最短路径问题。 ### 回答2: 在Matlab中,我们可以使用图算法来求解必经点最短路径问题。 首先,需要构建一个有向图对象来表示问题中的道路网络。可以使用Matlab中的graph函数来创建一个图对象,并使用addedge函数添加每条道路的起点、终点以及其长度。 接下来,我们可以使用Floyd算法来计算图中任意两点之间的最短路径。Floyd算法通过动态规划的方式,逐步更新图中每对顶点之间的最短路径。我们可以使用Matlab中的shortestpath函数来实现Floyd算法。 然而,必经点最短路径问题是Floyd算法的一个变种,需要添加额外的约束条件。为了实现这一点,我们可以修改图的邻接矩阵,将必经点之间的距离设置为0。这样,在计算最短路径时,Floyd算法就会强制经过这些点。 最后,根据Floyd算法的计算结果,我们可以得到包含必经点的最短路径。我们可以使用Matlab中的shortestpathtree函数来找到起点到终点的最短路径,并使用highlight函数来标记必经点。 综上所述,我们可以使用Matlab中的图算法和相关函数,来求解必经点最短路径问题。在求解过程中,需要构建图对象、修改图的邻接矩阵、计算最短路径,并最终找到包含必经点的最短路径。 ### 回答3: 必经点最短路径是指在一个无向图中,找到一条从起点到终点的路径,路径上必须经过指定的某些节点,并且路径的总长度最短。在Matlab中,可以通过以下步骤来实现必经点最短路径的计算: 1. 构建无向图:首先,根据问题的描述,使用Matlab中的图论工具箱构建一个无向图对象。可以使用graph或digraph函数来创建有向或无向图,并在函数的输入参数中指定节点和边。节点可以用数字或字符来表示,边可以用节点对来表示。 2. 设置节点和边的属性:根据问题的需求,为节点和边设置相关的属性。节点属性可以包括节点的名称、坐标等信息;边属性可以包括边的权重、长度等信息。 3. 设置起点和终点:在无向图中标记出起点和终点。 4. 设置必经点:根据问题的要求,在无向图中指定必经点。可以使用一个向量或矩阵来表示必经点,其中每个元素表示一个必经点的节点。 5. 计算最短路径:使用Matlab中的最短路径算法,如Dijkstra算法或A*算法,计算从起点到终点并经过必经点的最短路径。这些算法可以通过Matlab中的函数来实现,如shortestpath函数。 6. 输出最短路径:将计算得到的最短路径在图中标出,并将路径打印或显示出来。可以使用plot函数来绘制图形,使用text函数来标记节点,使用line函数来绘制边。 通过以上步骤,在Matlab中可以实现对必经点最短路径的计算和可视化展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值