分治法求最近点对问题

2023-11-01

目录

 

蛮力法

分治法

探究分治规模小于一定程度时采用暴力解法


蛮力法

  • 算法思想

蛮力法,顾名思义,即穷举所有点与点之间的距离,两层循环暴力找出最近点对。算法执行可视化如图1所示,word文档GIF静态显示,附件已含动图。

图1

  • 伪代码

matlab代码 

result=[];
for power=1:10
    scale=power*100000;
    count=0;
    for times=1:20
        x=randi(scale,1,scale);
        y=randi(scale,1,scale);
        tic;
        [i,j]=brute(x,y,scale);
        count=count+toc;           
    end
    count=count/20;
    result=[result,count];
end
function [mini,minj]=brute(x,y,scale)
    mini=1;
    minj=1;
    minDistance=Inf;
    for i=1:scale-1
        for j=1:scale
            if i==j
                break
            end
            distance=(x(i)-x(j))^2+(y(i)-y(j))^2;
            if distance<minDistance
                mini=i;
                minj=j;
                minDistance=distance;
            end
        end
    end
end
  • 实验结果

环境为MATLAB,数据规模为1w到5w,运行结果如图2所示。

图2

具体数据如表1所示。

表1

分析:

由实验结果可知,蛮力法的实验值与理论值基本一致,算法的时间复杂度确实为O(n2),确实很慢。

分治法

  • 算法思想

先对点进行预处理按横坐标排序,然后每次将点均分成左右两个子集,最短距离的两个点要么都在左子集,要么都在右子集,要么一个点在左子集中,一个点在右子集中,对于前面两种情况,问题变成递归寻找子集的最短距离,算法执行可视化如图3所示,word文档GIF静态显示,附件已含动图。

图3

而对于跨越中间线的情况,由左右两个子集可以算出一个目前最短距离minDistance,然后将距离中间点的距离小于minDistance的点找出来,如图4所示。

图4

如果存在最短距离,那么一定是一边一个点,所以我们需要将两边点的距离算一下,实际上,我们需要对于一边的点,我们需要计算距离的点最多不超过4个,因为同一边的点与点之间的距离肯定大于等于minDistance,所以对于另一边的点来说,范围小于minDistance内的点不会超过4个,如图5所示。

图5

  • 伪代码

matlab代 

result=[];
for power=1:10
    scale=power*100000;
    count=0;
    for times=1:20
        x=randi(scale,1,scale);
        y=randi(scale,1,scale);
        tic;
        [x,y]=Quick(1,scale,x,y);
        [mini,minj,minDistance]=divide(x,y,scale);
        count=count+toc;           
    end
    count=count/20;
    result=[result,count];
end
function [mini,minj,minDistance]=brute(x,y,scale)
    mini=1;
    minj=2;
    minDistance=Inf;
    for i=1:scale-1
        for j=i+1:scale
            distance=(x(i)-x(j))^2+(y(i)-y(j))^2;
            if distance<minDistance
                mini=i;
                minj=j;
                minDistance=distance;
            end
        end
    end
end
function [mini,minj,minDistance]=divide(x,y,scale)
    if length(x)<3
        [mini,minj,minDistance]=brute(x,y,scale);
        return;
    end
    half=floor(scale/2);
    [i,j,minLeft]=divide(x(1:half),y(1:half),half);
    [ii,jj,minRight]=divide(x(half+1:scale),y(half+1:scale),scale-half);
    if minLeft<minRight
        minDistance=minLeft;
        mini=i;
        minj=j;
    else
        minDistance=minRight;
        mini=ii;
        minj=jj;
    end
    left=[];
    right=[];
    for i=half-1:-1:1
        if abs(x(i)-x(half))>=sqrt(minDistance)
            break
        end
        left=[left,i];
    end
    for i=half+1:scale
        if abs(x(i)-x(half))>=sqrt(minDistance)
            break
        end
        right=[right,i];
    end
    for i=1:length(left)
        for j=1:length(right)
            if j>3
                break
            end
            distance=(x(left(i))-x(right(j)))^2+(y(left(i))-y(right(j)))^2;
            if distance<minDistance
                mini=left(i);
                minj=right(j);
                minDistance=distance;
            end
        end
    end
    for i=1:length(right)
        for j=1:length(left)
            if j>3
                break
            end
            distance=(x(left(j))-x(right(i)))^2+(y(left(j))-y(right(i)))^2;
            if distance<minDistance
                mini=left(j);
                minj=right(i);
                minDistance=distance;
            end
        end
    end
end
function[x,y]=Quick(low,high,x,y)
    i=low;
    j=high;
    pivot=x(low);
    temp=y(low);
    while low<high
        while low<high&&pivot<=x(high)
            high=high-1;
        end
        if low<high
            x(low)=x(high);
            y(low)=y(high);
            low=low+1;
        end
        while low<high&&pivot>x(low)
            low=low+1;
        end
        if low<high
            x(high)=x(low);
            y(high)=y(low);
            high=high-1;
        end
    end
    x(low)=pivot;
    y(low)=temp;
    if i<low-1
        [x,y]=Quick(i,low-1,x,y);
    end
    if high+1<j
        [x,y]=Quick(high+1,j,x,y);
    end
end
  • 算法复杂度

对于数据规模为n的情况,二分的次数为log2n次,而计算跨中间线距离的时候计算次数小于3n,即此处的时间复杂度是线性的,即T(n)=T(n/2)+O(n),可算得T(n)=nlogn。

  • 实验结果

先在小规模数据上跑,环境为MATLAB,数据规模为1w到5w,运行结果如图6所示。

图6

具体数据如表2所示。

表2

数据规模为10w到100w,运行结果如图7所示。

图7

具体数据如表3所示。

表3

分析:

由实验结果可知,分治法明显远远快于蛮力法,小规模数据时实验值略小于理论值,大规模时实验值与理论值基本一致。

探究分治规模小于一定程度时采用暴力解法

由于分治时不断递归调用函数,程序开销较大,考虑当分治到数据规模小于一定程度时采用暴力解法的运行效果,数据规模为1w,参数设置100到1000测试,结果如图8所示。

图8

由实验结果可知,分治规模达到200时使用暴力效果最佳,将参数设置为200,在数据规模为1w到5w上与原始分治法对比,如图9所示。

图9

在数据规模为10w到100w上与原始分治法对比,如图10所示。

图10

分析:

由实验结果可知,在分治规模小于一定数量时采用暴力求解效率更快,特别是在数据规模大的时候,这种暴力分治相结合的方法相比原始分治法具有很大的优势。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分治法求最近点对问题 的相关文章

随机推荐

  • sqlserver远程链接设置

    需要别人远程你的数据库 首先需要的是在一个局域网内 或者连接的是同一个路由器 接下来就是具体步骤 1 首先是要检查SQLServer数据库服务器中是否允许远程链接 其具体操作为 1 打开数据库 用本地帐户登录 右击第一个选项 选择属性 2
  • 矩阵键盘(stm32f103)

    最近需要用到矩阵键盘 在网上搜了很久看见的大多数都是根据判断寄存器的值来进行矩阵键盘取值 反正我找了一天 免费的文章 大都是这样的 付费的我也不知道 因为本人是初学者 对寄存器的操作不懂 刚开始也照着写了 逻辑上没有问题 但最后返回不了值
  • vant组件时间选择器修改时间格式以及默认展示当天时间

    vant的时间控件默认展示当天时间
  • 源码安装以太坊/wtc

    1 安装go 先更新一下 sudo apt get update sudo apt get y upgrade 下载源码https www golangtc com download 并解压 sudo tar xvf go1 9 2 lin
  • SQL盲注及python脚本编写

    1 什么是盲注 盲注就是在 sql 注入过程中 sql 语句执行的选择后 选择的数据不能回显 到前端页面 此时 我们需要利用一些方法进行判断或者尝试 这个过程称之为盲注 从 background 1 中 我们可以知道盲注分为三类 基于布尔
  • 基于 SpringMvc + OpenCV 实现的答题卡识别系统(附源码)

    java opencv 项目介绍 OpenCV是一个基于BSD许可 开源 发行的跨平台计算机视觉库 它提供了一系列图像处理和计算机视觉方面很多通用算法 是研究图像处理技术的一个很不错的工具 最初开始接触是2016年因为公司项目需要 但是当时
  • AlertDialog全屏显示的问题

    有时候 我们需要直接显示全屏的dialog 平常的时候会有一圈边框 不好看 第一步 编写style 第二步 在使用的时候带入 最简单的全屏就这么完成了 简单不 咩哈哈哈哈哈哈哈
  • Python入门实战题目

    1 有1 2 3 4个数字 能组成多少个互不相同且无重复数字的三位数 都是多少 2 两个乒乓球队进行比赛 各出三人 甲队为a b c三人 乙队为x y z三人 已抽签决定比赛名单 有人向队员打听比赛的名单 a说他不和x比 c说他不和x z比
  • Python3 [爬虫实战] Redis+Flask 动态维护cookies池(上)

    Redis 使用 1 首先去官网下载Reidszip文件 http www redis cn topics config html 2 Reids的安装 直接解压缩zip文件 然后放在一个文件夹中 在文件夹路径下用dos窗口启动服务器端 r
  • 入门算法题002

    题目 给你一个正整数n 假设有两个质数加起来等于n 问一共有多少组这样的质数 思路 1 我们得要先有一个函数去判断是否是质数 2 循环拆解为两个数 暴力拆解 试下10 15分钟内做出来 public class Leecode002 pub
  • selenium爬虫运行慢如何解决?

    Selenium作为一个强大的自动化工具 可用于编写爬虫程序 尽管Selenium在处理动态网页上非常强大 但对于静态网页爬简单数据提取 使用轻量级库或工具可能更加上所述 Selenium作为一个灵活可定动化工具 在需要模拟用户行为 处理动
  • VS2005中分页和多列排序

    最近在使用ASP net 2 0的GridView 控件时 发现排序与分页功能Microsoft实现的都很简单 比如排序 在点击列名的时候来触发整页的PostBack 然后排序 但是在列头上没有一个显示升序降序的图标 这会让最终用户使用时很
  • OJ在线编程常见输入输出练习(11题)

    1 输入包括两个正整数a b 1 lt a b lt 10 9 输入数据包括多组 输出描述 输出a b的结果 输入例子1 1 5 10 20 输出例子1 6 30 import java io BufferedReader import j
  • java web 项目配置日志框架log4j

    第一步 log4j 框架所关联的第三方jar 文件 commons logging xxx jar log4j xxx jar slf4j api xxx jar slf4j log4j12 xxx jar 以下是我搭建web框架集成log
  • 【C++】“没有可用成员”问题的原因之一

    今天碰到一个定义类成员函数的时候一直提示没有可用成员的问题 琢磨半天终于解决 记录一下 以免再犯 问题描述 在头文件中声明了名称空间SALES 并在名称空间中声明了类Sales 在类中声明了一系列类成员后 切换到另一个cpp文件中定义相关的
  • 基于CIFAR100的VGG网络结构详解

    基于CIFAR100的VGG网络详解 码字不易 点赞收藏 1 数据集概况 1 1 CIFAR100 cifar100包含20个大类 共100类 train集50000张图片 test集10000张图片 CIFAR100下载地址 http w
  • QTday3(QT实现文件对话框保存操作、实现键盘触发事件【WASD控制小球的移动】)

    1 实现文件对话框保存操作 include widget h include ui widget h Widget Widget QWidget parent QWidget parent ui new Ui Widget ui gt se
  • Unity3d 在HDRP项目中更换天空球

    两种情况 首先是直接通过unityhub创建的HDRP工程中 选中Sky and Fog Volume 进行如下图中标注的操作即可 其次是旧工程中 看到此教程说明你已经将旧工程升级到新的渲染管线工程 就略过升级旧工程的步骤直接开始配置天空盒
  • iptables 查看相关命令

    参考 https www zsythink net archives 1493 一些命令的总结 1 查看对应表的所有规则 t 指定要操作的表 省略 t 表名时 默认表示操作filter 表 L 表示列出规则 即查看规则 iptables t
  • 分治法求最近点对问题

    目录 蛮力法 分治法 探究分治规模小于一定程度时采用暴力解法 蛮力法 算法思想 蛮力法 顾名思义 即穷举所有点与点之间的距离 两层循环暴力找出最近点对 算法执行可视化如图1所示 word文档GIF静态显示 附件已含动图 图1 伪代码 mat