递归、分治、分类和最小距离点对的lisp实现

给定平面上的一个数量为n的点集,如何能有效地找出距离最近的点对呢?(在实际中有着应用,而且给出的是点对的集合,也就是在误差范围内的所有点对都找出来)。

这个问题很容易理解,似乎也不难解决。我们只要将每一点与其他n-1个点的距离算出,找出达到最小距离的两个点即可。然而,这样做效率太低,需要O(n^2)的计算时间。当数量规模较小时,尚能解决,但一旦规模达到万级以上,其速度之慢,时间之长,无法令人忍受。下面我给出这个问题的一个θ(nlogn)算法。

在这个算法中,我利用了递归、分治和分类思想。

递归算法是自身调用自身函数的一种算法,例如求阶乘:

(defun jc(n) (if (= n 0) 1 (* n (jc (1- n)))))

分治算法是对于一个规模为n的问题,把它分解成为K个规模较小的子问题,这些子问题互相独立,且结构与原来问题的结构相同。在解这些子问题时,又对于每一个子问题进行进一步的分解,直到某个阈值为止。递归地解决这些子问题,再把各个子问题的解合并起来,就得到原来问题的解。因此递归一般和分治联系在一起。

对于求最小距离的解,我参考了一些资料,他们给出的大多是C++

程序,我看不懂,只好按照算法和思想来设计lisp程序。

闲话少说,先看源程序:

[php]

;;***************

;;程序主段-------

(defun f2 (ptlist / l p1 p2 p3 dd 3pmind 3plist ptlist1 ptlist2

ptlist3 ptlist4 n m midpt mind1 mind2 mindt a b c

d Dismin Dnmin nplist mindi)

(setq l (length ptlist))

(cond

( (= l

2)

(list (distance (car ptlist) (cadr ptlist)) (list ptlist))

)

( (= l

3)

(progn

(setq p1 (car ptlist) p2 (cadr ptlist) p3

(caddr ptlist))

(setq dd

(list (list (distance p1 p2) (list p1 p2))

(list (distance p1 p3) (list p1 p3))

(list (distance p2 p3) (list p2 p3))

)

)

(setq 3pmind (apply 'min (mapcar 'car

dd)))

(setq 3plist nil)

(foreach 3name dd

(if (equal (car 3name)

3pmind 1e-8)

(setq 3plist (cons (cadr 3name) 3plist))

)

)

(list 3pmind 3plist)

)

)

( (> l

3)

(progn

(setq n (/ l 2) m (- l n))

(setq ptlist1 (cut ptlist 0 (1- m)))

(setq ptlist2 (cut ptlist m l))

(setq midpt (last ptlist1))

(setq mind1 (f2 ptlist1))

(setq mind2 (f2 ptlist2))

(setq mindT

(cond

((equal (car mind1) (car mind2) 1e-8)(list (car mind1) (append

(cadr mind1) (cadr mind2))))

((< (car mind1) (car mind2)) mind1)

(t mind2)

)

)

(setq mindi (car mindT))

(setq a (- (car midpt) mindi) b (car

midpt))

(setq ptlist3 (searchX ptlist1 a b))

(if (/= ptlist3 nil)

(progn

(setq Dismin nil)

(foreach name ptlist3

(setq a (car midpt) b (+ (car midpt) mindi) c (- (cadr name) mindi)

d (+ (cadr name) mindi))

(setq ptlist4 (searchXY ptlist2 a b c d))

(if (/= ptlist4 nil)

(setq Dismin (cons (6ptmin ptlist4 name) Dismin))

)

)

(if (= Dismin nil)

mindT

(progn

(setq Dnmin (apply 'min (mapcar 'car Dismin)) nplist nil)

(foreach npname Dismin

(if

(equal (car npname) Dnmin 1e-8)

(setq nplist (append (cadr npname) nplist))

)

)

(cond

((equal

(car mindT) Dnmin 1e-8) (list Dnmin (append nplist (cadr

mindT))))

((<

(car mindT) Dnmin) mindT)

(t (list Dnmin nplist))

);;for inest cond

);;for inest if-progn

);;for inest if

);;for if-progn

mindT

);;for if

);;for cond-last-progn

);;for

cond-last

);;for cond

);;for defun

;;***************

;;以下为测试和附加程序:

(defun C:te ();;(/ olderr en errmsg oldmode oce sl ss t0 ptlist

pp pp1)

;;定义错误函数和预处理

(setvar "errno" 0)

(setq olderr *error*)

(defun *error* (msg)

(setq en

(getvar "errno"))

(setq

errmsg (strcat "errno=" (itoa en) "\nError:" msg))

(alert

errmsg)

(setq

*error* olderr)

)

(graphscr)

(setq oldmode (getvar "osmode"))

(setq oce (getvar "cmdecho"))

(setvar "cmdecho" 0)

(command ".ucs" "W")

;;也可以用其他方式取得点集

(setq sl '((0 . "POINT")))

(setq t0 (getvar "TDUSRTIMER"))

(setq ss (ssget sl))

(setq ptlist (getpt ss))

;;分类

(setq t0 (getvar "TDUSRTIMER"))

(setq ptlist (sortx ptlist))

(princ "\n函数排序用时")

(princ (* (- (getvar "TDUSRTIMER") t0)

86400))

(princ "秒")

;;函数用时估算,以了解函数性能

(setq t0 (getvar "TDUSRTIMER"))

(setq pp1 (f2 ptlist) pp (car (cdr pp1)))

(princ "\n函数查找用时")

(princ (* (- (getvar "TDUSRTIMER") t0)

86400))

(princ "秒")

(if (= nil pp)

(progn

(alert "不存在有最小距离的一对点!")

(command ".ucs" "p")

(setvar "osmode" oldmode)

(setvar "cmdecho" oce)

(princ)

)

(progn

;;画最短距离的点对集的连线,可能有多条

(setvar "osmode" 0)

(foreach nn pp

(entmake

(append

'((0 . "line")(100 . "AcDbEntity")(100 . "AcDbLine"))

(list (cons 10 (car nn)))

(list (cons 11 (cadr nn)))

(list (cons 62 1))

)

)

)

(command ".ucs" "P")

(setvar "osmode" oldmode)

(setvar "cmdecho" oce)

(princ)

)

)

)

;;取点函数,其中i为点的编号

(defun getpt (ss / i listpp a b c)

(setq i 0 listpp nil )

(if ss

(repeat

(sslength ss)

(setq a (ssname ss i))

(setq b (entget a))

(setq c (cdr (assoc 10 b)))

(setq listpp (cons c listpp))

(setq i (1+ i))

)

)

(reverse listpp)

)

;;从J到K的表

(defun cut (ptlist j k / i ptlist1)

(setq i 0 ptlist1 nil)

(foreach n ptlist

(if (and

(>= i j) (<= i k) )

(setq ptlist1 (cons n ptlist1))

)

(setq i

(1+ i))

)

(reverse ptlist1)

)

;;对X排序

(defun sortX (ptlist)

(mapcar '(lambda (x) (nth x ptlist))

(vl-sort-i ptlist '(lambda (e1 e2) (< (car e1)(car e2))))

)

)

;;在带形区域查找

(defun searchX (ptlist1 x1 x2 / pp n)

(setq pp nil)

(foreach n ptlist1

(if (and

(>= (car n) x1)(<= (car n) x2))

(setq pp (cons n pp))

)

)

(reverse pp)

)

;;在矩形区域查找

(defun searchXY (ptlist2 x1 x2 y1 y2 / pp n)

(setq pp nil)

(foreach n ptlist2

(if (and

(>= (car n) x1)

(<= (car n) x2)

(>= (cadr n) y1)

(<= (cadr n) y2)

)

(setq pp (cons n pp))

)

)

(reverse pp)

)

;;最多6点最小距离

(defun 6ptmin (ptlist4 pt / 6pmin 6plist)

(setq 6pmin (mapcar '(lambda (x) (distance x

pt)) ptlist4))

(setq 6pmin (apply 'min 6pmin) 6plist

nil)

(foreach 6name ptlist4

(if

(equal (distance 6name pt) 6pmin 1e-8)

(setq 6plist (cons (list pt 6name) 6plist))

)

)

(list 6pmin

6plist)

)

[/php]

在这个论坛上,比较了一些别人写的代码,(大都是平方级别的,有的甚至更高),发现在时间上还是比平方级以上的要快很多。但是还没有做最优处理,希望大家多多提意见给我。

[email]highflybird@sina.com[/email]

2006-11-25,kunming

这个题的算法步骤如下:

1、首先把点集按照X从小到大分类,

2、先求两点和三点的最小距离点对。

3、对于大于三点以上的N个点,做如下考虑:

A,把点按照中位数分开。(例如,19个点,则左边10个,右边9个,18个对分)

B,对两边分别用递归方法求解。 得到两个最小的距离d1和d2

C,比较d1或者d2大小,取最小的为dmin

D,设置中位点X坐标为xmid ,对于落在 (xmid-dmin,xmid)

区域上的点(xscan, yscan) 进行扫描X落在(dmin,xmid+dmin)Y落在(

yscan-dmin,yscan+xdmin)

右边的点(理论证明最多有6个这样的点),分别求左边扫描的点跟右边区域的点的距离,找到距离的最小,然后从最小的合集中找到最小

midarea-min,把这个值跟dmin做比较,这样就可以得出最小的距离以及它们的点对。

如果不明白的话,可以参考一些书籍和网上的资料。

lisp 任意点 曲线距离_递归、分治、分类和最小距离点对的autolisp实现相关推荐

  1. lisp 任意点 曲线距离_奇怪的知识增加了:把标准形式的双曲线旋转来解决问题...

    依旧的祖传开头:事先说明:笔者初三,如在叙述中有不严谨的地方,还请诸位指出,自当感激不尽. (想和大家唠个嗑:由于疫情影响,不能提前去高中上课,目前在初中陪同学准备中考,学业实在繁忙,更文力不从心,还 ...

  2. lisp 任意点 曲线距离_数学篇|看完这篇,秒杀所有圆锥曲线小技巧

    今天为大家带来的是小袁老师为大家总结的圆锥曲线题目的解题技巧,有例题有讲解! 善用几何性质 圆锥曲线的几何性质可以说是基础中的基础,它以及它引申出的焦点三角形面积公式在题目中也是被广泛地用到. 首先我 ...

  3. 任意点 曲线距离_中级数学11-曲线函数

    距离.中点.圆 抛物线 椭圆 双曲线 非线性方程 曲线 本章介绍曲线及其性质.这里应用两圆锥体构成的推覆体与一个平面相交的截面,形成的曲线. 从左到右截面:圆.抛物线.椭圆.双曲线 距离.中点.圆 应 ...

  4. lisp 任意点 曲线距离_lisp程序能求多段线上任意一点到其中一个端点的距离,,每次要量桩号很烦...哪位大侠给个..谢谢了...........

    ;;;可导出桩号的代码 (defun C:GM (/ cur pt fi mile) ;;自定义错误处理函数 (defun myerror (s) (if (and (/= s "函数被取消 ...

  5. Algorithms_算法思想_递归分治

    文章目录 引导案例 递归的定义 什么样的问题可以用递归算法来解决 递归如何实现以及包含的算法思 递归的公式 斐波那契数列代码实现 递归的时间复杂度和空间复杂度 递 与 归 递归的优化 优化方式一:不使 ...

  6. [剑指offer][JAVA]面试题第[33]题[二叉搜索树的后序遍历][单调栈][递归分治]

    [问题描述][中等] 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果.如果是则返回 true,否则返回 false.假设输入的数组的任意两个数字都互不相同.参考以下这颗二叉搜索树:5/ ...

  7. 蓝桥杯-皮亚诺曲线距离

    观察皮亚诺曲线,我们可以得到一下结论. 将整个图形分成九个区域,编号如下: 我们规定一号区域的方向为标准方向,则所有区域的方向为 1:x不翻转,y不翻转 2:x翻转,y不翻转 3:x不翻转,y不翻转 ...

  8. 2020年第十一届蓝桥杯决赛JAVA B G题“皮亚诺曲线距离“

    2020年第十一届蓝桥杯决赛JAVA B G题"皮亚诺曲线距离" 2020国赛 JAVA B组 个人题解目录 [问题描述] 皮亚诺曲线是一条平面内的曲线. 下图给出了皮亚诺曲线的 ...

  9. 2020第十一届蓝桥杯国赛(决赛)C/C++ B组F题皮亚诺曲线距离题解

    F: 皮亚诺曲线距离 [问题描述] 皮亚诺曲线是一条平面内的曲线. 下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3 × 3 的方格中的每一个格子,最终到达右上角的一条曲线. 下图给 ...

最新文章

  1. PAT甲级1056 Mice and Rice:[C++题解]模拟、排名
  2. 2022-01-12
  3. 软件体系架构:RM-ODP参考模型简介
  4. oracle数据库安装自动化,自动化Oracle数据库静默安装
  5. 05 state与setState、单向数据流
  6. python内置类型_Python内置对象类型
  7. 工作几年了,原来我只用了数据校验的皮毛
  8. python格式字符_python格式字符
  9. 全球顶级开源大神们现身 COSCon‘20
  10. 前端智勇大闯关-第二季-第三题
  11. Halcon学习路线——Blob分析(2)
  12. Java开发过程中需要注意的技巧有哪些?
  13. oracle 无法套取,mycat-oracle报java.sql.SQLException: 无法从套接字读取更多的数据
  14. Atitit 部署了个webdav服务 as root 目录 1.1. WEB-INF copy to root dir only a web.xml use... 1 1.2. Java.ba
  15. Cplex入门教程(一)
  16. SOUI中菜单的简单实现
  17. Struts1标签库如何升级到Struts2
  18. 本地化差分隐私(Local Differential Privacy)浅析
  19. 电子线路与电磁干扰/电磁兼容设计分析
  20. 解决java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionV

热门文章

  1. (译)如何优化cocos2d程序的内存使用和程序大小:第一部分
  2. 黄聪:Delphi 日期格式问题 - is not a valid date
  3. Win10 安装 VS2015 失败解决办法
  4. oracle创建触发器
  5. Django简单介绍-基础1
  6. Spring Boot工程在IDEA中运行报错
  7. Win10系列:C#应用控件进阶10
  8. Linux 性能分析工具 nmon for Linux
  9. 配置网络策略中的 NAP 条件
  10. CSS基础知识真难啊