用分治法解决最近点对问题:python实现
最近点对问题:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。需要说明的是理论上最近点对并不止一对,但是无论是寻找全部还是仅寻找其中之一,其原理没有区别,仅需略作改造即可。本文提供的算法仅寻找其中一对。
解决最近点对问题最简单的方法就是穷举法,这样时间复杂度是平方级,可以说是最坏的策略。如果使用分治法,其时间复杂度就是线性对数级,这样大大提高了效率。
首先用分治法解决该问题的基本思路可以参考 http://blog.csdn.net/lishuhuakai/article/details/9133961 ,说的很详细,但大致思路就是先根据x轴把所有点平分,然后分别在每一部分寻找最近点对,最后通过比较选一个最小的。当然其中最核心的地方是跨域求距离,原文写的很清楚,在此就不再赘述了。
以下是代码:
from math import sqrt def nearest_dot(s):
len = s.__len__()
left = s[0:len/2]
right = s[len/2:]
mid_x = (left[-1][0]+right[0][0])/2.0 if left.__len__() > 2: lmin = nearest_dot(left) #左侧部分最近点对
else: lmin = left
if right.__len__() > 2: rmin = nearest_dot(right) #右侧部分最近点对
else: rmin = right if lmin.__len__() >1: dis_l = get_distance(lmin)
else: dis_l = float("inf")
if rmin.__len__() >1: dis_2 = get_distance(rmin)
else: dis_2 = float("inf") d = min(dis_l, dis_2) #最近点对距离 mid_min=[]
for i in left:
if mid_x-i[0]<=d : #如果左侧部分与中间线的距离<=d
for j in right:
if abs(i[0]-j[0])<=d and abs(i[1]-j[1])<=d: #如果右侧部分点在i点的(d,2d)之间
if get_distance((i,j))<=d: mid_min.append([i,j]) #ij两点的间距若小于d则加入队列
if mid_min:
dic=[]
for i in mid_min:
dic.append({get_distance(i):i})
dic.sort(key=lambda x: x.keys())
return (dic[0].values())[0]
elif dis_l>dis_2:
return rmin
else:
return lmin # 求点对的距离
def get_distance(min):
return sqrt((min[0][0]-min[1][0])**2 + (min[0][1]-min[1][1])**2) def divide_conquer(s):
s.sort(cmp = lambda x,y : cmp(x[0], y[0]))
nearest_dots = nearest_dot(s)
print nearest_dots
测试一下,比如说要找这些点中最近的一对s=[(0,1),(3,2),(4,3),(5,1),(1,2),(2,1),(6,2),(7,2),(8,3),(4,5),(9,0),(6,4)]
运行一下divide_conquer(s),最终打印出[(6, 2), (7, 2)],Bingo
用分治法解决最近点对问题:python实现的更多相关文章
- Leetcode 240 Search a 2D Matrix II (二分法和分治法解决有序二维数组查找)
1.问题描写叙述 写一个高效的算法.从一个m×n的整数矩阵中查找出给定的值,矩阵具有例如以下特点: 每一行从左到右递增. 每一列从上到下递增. 2. 方法与思路 2.1 二分查找法 依据矩阵的特征非常 ...
- hdu 1007 Quoit Design(分治法求最近点对)
大致题意:给N个点,求最近点对的距离 d :输出:r = d/2. // Time 2093 ms; Memory 1812 K #include<iostream> #include&l ...
- 分治法解决合并排序(c++和Java源代码)
Java源代码 public class Mergesort1 { public static void merge(int[]a,int low,int mid,int high){//对两组已经排 ...
- p1257 平面上最接近点对---(分治法)
首先就是一维最接近点的情况... #include<iostream> #include<cstdio> #include<cstring> #include< ...
- 分治法求一个N个元素数组的逆序数
背景 逆序数:也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时, ...
- 分治法(一)(zt)
这篇文章将讨论: 1) 分治策略的思想和理论 2) 几个分治策略的例子:合并排序,快速排序,折半查找,二叉遍历树及其相关特性. 说明:这几个例子在前面都写过了,这里又拿出来,从算法设计的策略的角度把它 ...
- python 实现分治法的几个例子
分治法所能解决的问题一般具有以下几个特征: 1) 该问题的规模缩小到一定的程度就可以容易地解决 2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质. 3) 利用该问题分解出的子 ...
- C语言实现快速排序法(分治法)
title: 快速排序法(quick sort) tags: 分治法(divide and conquer method) grammar_cjkRuby: true --- 算法原理 分治法的基本思 ...
- 分治法及其python实现例子
在前面的排序算法学习中,归并排序和快速排序就是用的分治法,分治法作为三大算法之一的,有非常多的应用例子. 分治法概念 将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题-- ...
随机推荐
- 门控开关项目--整流桥分析,LED限流电阻选择
完整的原理图 常见电阻 常见的精度分为5% 和1%精度,碳膜电阻5%精度,金属膜电阻1%精度. 常见的阻值有 10R, 100R, 330R, 1K, 2K, 3K, 5.1K, 10K, 15K, ...
- spring +springmvc+mybatis组合mybatis-config.xml文件配置
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC &q ...
- c++数组易错点总结
c++数组 1.只有在定义数组是才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组 int cards[4] = { 3 , 6 , 8 , 10}; //ok int hands[4] ...
- hightcharts在移动端运用 FastClick后苹果上legend点击失效的解决办法
问题:在移动端做图表运用了hightcharts,引用了fastclick来消除300ms的延迟,但是发现苹果(安卓正常)上hightcharts的legend点击不起作用了,必须长按才行. 使用fa ...
- 00002、div的文字垂直居中与背景的渐变
1.div可以放多行的文字,当显示文字较少时,文字可垂直居中 text-align: center; display: table-cell; vertical-align: middle; text ...
- SecureFX 乱码问题
英文平时连终端的都是用SecureCRT, 今天试了一些SecureFX, 结果乱码了, 把redhat下的中文桌面标题显示乱码, 然后参考了一下别的前辈, 完美解决, 下面是解决办法: 1.找到配置 ...
- css 子div自适应父div高度
<div class="out"> <div class="a"></div> <div class="b& ...
- 如何在通过knockout数据绑定的DOM元素上添加事件
通过knockout数据绑定的DOM元素,通过chrome控制台打断点知道,DOM元素会被暂时隐藏,使用document.querySelector()是获取不到的,会显示null,直到数据绑定完成才 ...
- 1010: [HNOI2008]玩具装箱toy [dp][斜率优化]
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...
- 初学Python(十)——列表生成式
初学Python(十)--列表生成式 初学Python,主要整理一些学习到的知识点,这次是列表生成式. # -*- coding:utf-8 -*- ''''' 列表生成式 ''' #一行代码表达所有 ...