算法分析与复杂性理论-实验报告-求最近点对的问题

深圳大学实验报告
教务部制
1.对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,
输出是N点中具有最短距离的两点。

2.要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。

3.要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。

4.分别对N=100,1000,10000,100000 ,统计算法运行时间,比较理论效率与实测效率
的差异,同时对蛮力法和分治法的算法效率进行分析和比较。

5.利用Unity3D输出分治算法中间每个步骤的计算结果,并增设help按钮,详细解释
算法思想。

算法思想提示
1.预处理:根据输入点集S中的x轴和y轴坐标进行排序,得到X和Y,很显然此时X和Y 中的点就
是S中的点。

2.点数较少时的情形
直接计菊
只有三个疽
3.点数|S|>3时,将平面点集S分割成为大小大致相等的两个子集S L和S R,选取一个垂直
线L作为分割直线,考虑X L和X R,Y L和Y R,这里还需要排序吗?
4.两个递归调用,分别求出S L和S R中的最短距离为d i和d r。

5.取d=min(dl, dr),在直线L两边分别扩展d,得到边界区域Y, Y'是区域Y中的点按照y
坐标值排序后得到的点集,Y'又可分为左右两个集合Y 'L和Y 'R
L.一
L<d
L+d
6.对于Y'L中的每一点,检查Y'R中的点与它的距离,更新所获得的最近距离
实验过程及内容:
(实验代码已作为附件提交,名为“算法实验二.cpp)
当点的数量小丁3时,直接计算,当点的个数大丁3时,采用分治法当N=1时
当N=2时
只有两个点,最近点对就是这两个点
测试数据为(1,1 ) (2,2)
预期结果为d=1.414
使用蛮力法求最近点对,核心代码如下
〃求距离平方的函数
double Distinyuish2(Node a t Node b)
return ((d.x-b.x)*(a.x-b.x)) + ((a.y-tj.y)*(a.y-b.y));
〃蛮力法求最近对
uoid BriiteForce(const HList & L,CloseHode & cnode,int begin v int end)
For(int i=t)egin;i<=end;i*+)
Forfinit j<-end;j + + )
double space = Di stinguish2(L.data[i],L.data[j]); iF<sp^ce<cnode.5pact)
cnode_a=L.data[l]; cnade.b=L.data[j]; cnode .space=space;
(计算两点之间的距离,分别将每个点与其它点的距离求出来,找出最近点距离)
当N>3时,使用分治法的情况核心代码如下:
;15E 〃当n》3时进行分治
<
APOIHT *SL-nev fi_POINT[(high-low)/2+1];
■[POINT *SR-nev A>0IHT[ (hi^i-low)/2];
n)= (high-low)/2; /成曦(组以缺)界划分为茜半
j=k=t);
for(i=B;i<=high-lou;i*+)
if(V[i]*indeK<=n)
{SL[ ji ] T [i];〃收集左边子集中的最近点对pise
{
SR[kt+]=Y[i];〃收集右边子集中的最近点对
>
)
closest (K.SL,low,■,al,bl,dl);//i+ 算左边子集的最近点对
closes t (X,Sft,m+1,tiigh,ar.br,dr 算右边子靠的最近点对
if(dl<dr)
;b=bl;d=dl;
}
else
(
a=ar;b=tjr ;d=dr;
POIlfT *2=new POI NT[higti-low+1 ];
k=o;
For(i=B;i<=t*igh-lcw;i*+)//收集距离中线?寤小于U的元素,保存S懒组?中(
iF(f=abstX[n] .x-V[l] .x)<d>
2(k].x=V[i],x;
£[k^+].y=V[i]^:
for(i-l;l<k;l++)
< far(j=i>1;(-y-Z[i] j++)
dl=aist(Z[i]^[j]);
{
a = 2[iJ;
b - Z[j];
ri = d) ■
当N=6时,给定一组测试数据
下面随机生成N个点的平面坐标,求解最近点对。

并计算时间
产生随机数代码:
srand((unsigned)tine(NULL));
i nt n;
cout<Cl§输入点的个数,七
cin>>n;
//cout«-Sf输入各个点的坐标,'«^dl:
POINT *X=new P0iHT[n];
for(int i=0;i<n;i++)
<
X[i] .x=rand()^100;
K[i] .j|^rand()^1BO;
计算时间代码
timet timel,time2; //
tinel-time(NULL); //方法调用前设置一个tinel
“TimUNULL);〃弦样得到的就是妙
〃―痕_t t2-GetTickCount();〃这样得到的就是毫秒
tineZ-tine(NULL);//方法调用前设置一个tineZ //cout«,,tine2:,,«double(tine2)«endl;
cout<<"耗时为!"《《douhleUtimN-timel)) V"^l)"«endl;//统计时间为time?-timel
数据处理分析:
由以上数据可知,随着N的增大,分治法效率比蛮力法效率越来越高。

蛮力法求解最近对问题的过程是:分别计算每一对点之间的距离,然后找出距离最
小的那一对,为了避免对同一对点计算两次距离,只考虑i vj的那些点对(Pi, Pj)。

其实也就是组合的问题,即从n个点中选取两个点的所有组合情况的问题,共有(n*(n-1))种情况。

因此时间复杂度为:
T(n)=£Z 2 = 2L(n-i)=n(n-1) = O(n2) i 注j =i 1 i 1
治法求解含有n个点的最近对问题,其时间复杂性可由下面的递推式表示:
T(n) =2T(n 2) f(n)
合并子问题的解的时间f(n) = O(n),根据通用分治递推式可得T(n)=O(n log2 n)。

实验结论与体会:
分治法的思想就是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。

递归地解这些子问题,然后将各个子问题解合并得到原问
题的解。

通过本次试验我对分治法有了更深的了解。

利用分治法可以将问题简化,这有助于我们在实际中解决一些复杂性较大的问题,提高程序的运行效率。

指导教师批阅意见:
成绩评定:
指导教师签字: 备注:
注:1、报告内的项目或内容设置,可根据实际情况加以调整和补充。

2、教师批改学生实验报告时间应在学生提交实验报告时间后10日内。

Welcome To Download !!!
欢迎您的下载,资料仅供参考!。

合集下载

TSP实验报告

TSP实验报告

TSP实验报告(实验报告、研究报告)考核科⽬:算法分析与复杂性理论学⽣所在学院:计算机科学与技术学院学⽣所在学科:计算机应⽤技术姓名:学号:学⽣类别:研究⽣⼀、实验⽬的1.通过TSP算法的具体实现,加深对算法复杂分析的理解。

2.通过TSP算法的具体实现,提⾼对NP完全问题的认识。

3.通过TSP算法的具体实现,理解不确定性算法。

4.通过TSP算法的具体实现,理解不确定性算法。

⼆、实验环境实验平台:Visual C++编程语⾔:C++编程电脑配置:三、实验内容描述TSP(Travelling Salesman Problem)⼜称货郎担或巡回售货员问题,在运筹学、管理科学及⼯程实际中具有⼴泛的⽤途。

及⼯程实际中具有⼴泛的⽤途。

TSP问题是组合优化中的著名难题,⼀直受到⼈们的极⼤关注。

由于其NP难题性质,⾄今尚未完全解决。

此问题可以抽象描述为:给出⼀个n个顶点⽹络(有向或⽆向),要求找出⼀个包含所有n个顶点的具有最⼩耗费的环路。

其中,任何⼀个包含所有n个顶点的环路被称作⼀个旅⾏。

对于旅⾏商问题,顶点表⽰旅⾏商所要旅⾏的城市(包括起点)。

边上权值给出了在两个城市旅⾏所需的路程。

旅⾏表⽰当旅⾏商游览了所有城市后再回到出发点时所⾛的路线。

四、实验原理许多研究表明,应⽤蚁群优化算法求解TSP问题优于模拟退⽕法、遗传算法、神经⽹络算法、禁忌算法等多种优化⽅法。

为说明该算法,引⼈如下的标记: m表⽰蚁群中蚂蚁的数量;表⽰城市i和城市j之间的距离;表⽰t时刻位于城市i的蚂蚁数,显然应满⾜,表⽰t时刻在ij连线上的信息数量。

在算法的初始时刻,将m只蚂蚁随机地放到n座城市上,此时各路径上的信息量相等,设。

每只蚂蚁根据路径上保留的信息量独⽴地选择下⼀个城市。

在时刻t,蚂蚁k从城市i转移到城市j 的概率为其中,表⽰蚂蚁⾛下⼀步允许选择的所有城市,列表纪录了当前蚂蚁k所⾛过的城市,当所有n个城市都加⼊到中时,蚂蚁k便完成了⼀次循环,此时蚂蚁⾛所⾛过的路径便是问题的⼀个解。

分而治之算法---距离最近的点对

分而治之算法---距离最近的点对

距离最近的点对给定n 个点(xi,yi)(1≤i≤n),要求找出其中距离最近的两个点。

例14-7 假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。

若知道任意两个洞的最小距离,可估计金属断裂的概率。

这种最小距离问题实际上也就是距离最近的点对问题。

通过检查所有的n(n- 1 ) / 2对点,并计算每一对点的距离,可以找出距离最近的一对点。

这种方法所需要的时间为(n2 )。

我们称这种方法为直接方法。

图1 4 - 1 3中给出了分而治之求解算法的伪代码。

该算法对于小的问题采用直接方法求解,而对于大的问题则首先把它划分为两个较小的问题,其中一个问题(称为A)的大小为「n /2ù,另一个问题(称为B)的大小为「n /2ù。

初始时,最近的点对可能属于如下三种情形之一: 1) 两点都在A中(即最近的点对落在A中);2) 两点都在B中;3) 一点在A,一点在B。

假定根据这三种情况来确定最近点对,则最近点对是所有三种情况中距离最小的一对点。

在第一种情况下可对A进行递归求解,而在第二种情况下可对B进行递归求解。

if (n较小) {用直接法寻找最近点对R e t u r n ; }// n较大将点集分成大致相等的两个部分A和B确定A和B中的最近点对确定一点在A中、另一点在B中的最近点对从上面得到的三对点中,找出距离最小的一对点图14-13 寻找最近的点对为了确定第三种情况下的最近点对,需要采用一种不同的方法。

这种方法取决于点集是如何被划分成A、B的。

一个合理的划分方法是从xi(中间值)处划一条垂线,线左边的点属于A,线右边的点属于B。

位于垂线上的点可在A和B之间分配,以便满足A、B的大小。

例2-8 考察图14-14a 中从a到n的1 4个点。

这些点标绘在图14-14b 中。

中点xi = 1,垂线x = 1如图14-14b 中的虚线所示。

虚线左边的点(如b, c, h, n, i)属于A,右边的点(如a, e, f, j, k, l) 属于B。

最接近点对问题

最接近点对问题

一、最接近点对问题(一维)一、最接近点对问题(一维)最接近点对问题:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。

此时S中的n个点退化为x轴上的n个实数x1,x2,..,x n。

最接近点对即为这n个实数中相差最小的2个实数。

2、分析将所给的平面上n个点的集合S分成2个子集S1和S2,每一个子集中约有n/2个点,·然后在每一个子集中递归地求其最接近的点对。

S1和S2的最接近点对未必就是S的最接近点对,若是组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。

可是,若是这2个点别离在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它组成最接近点对的候选者,仍需做n2/4次计算和比较才能肯定S的最接近点对。

因此,依此思路,归并步骤耗时为O(n2)。

整个算法所需计算时间T(n)应知足:T(n)=2T(n/2)+O(n2)它的解为T(n)=O(n2)3、伪代码随机Randomfloat Random(){float result=rand()%10000;return result*;}返回最大、最小float Max OR Min(float s[],int p,intq)序实现#include<>#include<iostream>#include<cmath>using namespace std;const int M=50;D=i;X[i].x=Random();X[i].y=Random();c out<<"("<<X[i].x<<","<<X[i].y<<") ";}PointX a;PointX b;float d;Cpair2(X,number_used,a,b,d);cout<<endl;cout<<"the closest pair is ("<<<<","<<<<")和("<<<<","<<<<") "<<endl;cout<<"the min distance is "<<d<<endl;return 0;}float Random(){float result=rand()%10000;return result*;}=i;Y[i].x=X[i].x;Y[i].y=X[i].y;}PointY*tmpy=new PointY[n];MergeSort(Y,tmpy,0,n-1);PointY*Z=new PointY[n];closest(X,Y,Z,0,n-1,a,b,d);delete []Y;delete []Z;return true;}void closest(PointX X[],PointY Y[],PointY Z[], int l, int r,PointX& a,PointX& b,float& d){i f(r-l==1){>m) Z[g++]=Y[i];else Z[f++]=Y[i]; closest(X,Z,Y,l,m,a,b,d);float dr;PointX ar,br;closest(X,Z,Y,m+1,r,ar,br,dr);if(dr<d){a=ar;b=br;d=dr;}Merge(Z,Y,l,m,r);-Y[t].x)<d){Z[k++]=Y[t];}-Z[s].y<d;j++){float dp=dis(Z[s],Z[j]);if(dp<d){d=dp;a=X[Z[i].p];b=X[Z[j].p];} } } }template <typename Type>void Merge(Type c[],Type d[], int l, int m, int r){i nt i=l,j=m+1,k=l;w hile((i<=m)&&(j<=r))if(c[i]<=c[j])d[k++]=c[i++];elsed[k++]=c[j++];if(i>m)for(int q=j;q<=r;q++)d[k++]=c[q];elsefor(int q=i;q<=m;q++)d[k++]=c[q];}template <typename Type>void MergeSort(Type a[], Type b[],int left, int right){ // a[]为待排序的数组,left,right为a数组的下标,b[]为临时存放排好序的临时数组i f(left<right){int i=(left+right)/2;//取中点MergeSort(a,b,left,i);MergeSort(a,b,i+1,right);Merge(a,b,left,i,right);//归并到数组bCopy(a,b,left,right);//复制回数组a }}template <typename Type>void Copy(Type a[],Type b[], int right,int left) {for(int i=right;i<=left;i++)a[i]=b[i];}运行情况:。

蛮力法分治法求最近对

蛮力法分治法求最近对

实验题目设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

实验目的(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。

实验内容(包括代码和对应的执行结果截图)#include<iostream>#include<cmath>#include <windows.h>using namespace std;typedef struct Node{//定义一个点的结构,用于表示一个点int x;int y;}Node;typedef struct NList{//定义一个表示点的集合的结构Node* data;int count;}NList;typedef struct CloseNode{//用于保存最近两个点以及这两个点之间的距离Node a;Node b;double space;}CloseNode;int max;void create(NList & L){cout<<"请输入平面上点的数目:\n";cin>>max;L.count=max;L.data = new Node[L.count];//====================动态空间分配cout<<"输入"<<L.count<<"个点坐标X,Y,以空格隔开:"<<endl;for(int i=0;i<L.count;i++)cin>>L.data[i].x>>L.data[i].y;}//求距离平方的函数double Distinguish2(Node a,Node b){return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));}//蛮力法求最近对void BruteForce(const NList & L,CloseNode & cnode,int begin,int end){for(int i=begin;i<=end;i++)for(int j=i+1;j<=end;j++){double space = Distinguish2(L.data[i],L.data[j]);if(space<cnode.space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}}//归并排序void Merge(Node SR[],Node TR[],int i,int m,int n){//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]int j,k;for(j=m+1,k=i;i<=m&&j<=n;k++)if(SR[i].x<=SR[j].x) TR[k]=SR[i++];else TR[k]=SR[j++];while(i<=m) TR[k++]=SR[i++];while(j<=n) TR[k++]=SR[j++];}void Msort(Node SR[],Node TR1[],int s,int t){//将SR[s..t]归并排序为TR1[s..t]if(s==t) TR1[s]=SR[s];else{int m = (s+t)/2;Node *TR2=new Node[max];//new Node[t-s+1];//这个空间挂挂的,从s到t,这里是从0到t-sMsort(SR,TR2,s,m);Msort(SR,TR2,m+1,t);Merge(TR2,TR1,s,m,t);}}void MergeSort(NList L){Msort(L.data,L.data,0,L.count-1);}//分治法求最近对中间2d对称区的算法void Middle(const NList & L,CloseNode & cnode,int mid,int midX){int i,j;int d = sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)){j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count){//1,j++ 2<=,>=if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d))continue;double space = Distinguish2(L.data[i],L.data[j]);if(cnode.space>space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}i--;}}// ----------------------------------------------//分治法求最近对void DivideAndConquer(const NList &L,CloseNode & closenode,int begin,int end) {if((end-begin+1)<4) BruteForce(L,closenode,begin,end);else{int mid = (begin+end)/2;int midX = L.data[mid].x;DivideAndConquer(L,closenode,begin,mid);DivideAndConquer(L,closenode,mid+1,end);Middle(L,closenode,mid,midX);}}int main(){SYSTEMTIME sys;GetLocalTime( &sys );NList list;CloseNode closenode;closenode.space = 10000;create(list);cout<<"各点坐标为:"<<endl;for(int i=0;i<list.count;i++)cout<<"X="<<list.data[i].x<<" Y="<<list.data[i].y<<"\n";BruteForce(list,closenode,0,list.count-1);cout<<"用蛮力法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"==================================================== ================"<<endl;cout<<"用分治法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;MergeSort(list);cout<<"经过归并排序后的各点:"<<endl;for(int j=0;j<list.count;++j)cout<<"X="<<list.data[j].x<<" Y="<<list.data[j].y<<"\n";DivideAndConquer(list,closenode,0,list.count-1);cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;return 0;}实验结果分析由以上数据可知,分治法效率比蛮力法效率高。

算法分析与设计实验报告一

算法分析与设计实验报告一

算法分析与设计实验报告学生姓名:系别:专业与班号:学号:实验名称:Strassen’s 矩阵乘法和最近点对算法实验目的1、理解“分治法”算法设计思想及其实现步骤2、掌握分治算法效率递归分析方法3、掌握主方式求解递归式方法实验内容及要求1、利用计算机程序设计语言,实现教材第28.2 章介绍的“Strassen’s 矩阵乘法算法”,自主生成两个8×8 的矩阵,检验算法的正确性并输出算法结果。

2、比较 Strassen’s 矩阵乘法算法和数学定义的矩阵乘法算法效率之间的区别,并用直观的表达方式把两种不同矩阵乘法的效率随矩阵维数的变化趋势。

3、利用计算机程序设计语言,实现教材第33.4 章介绍的“最近点对算法”,在拟定的二维空间点集上检验算法的正确性并输出算法结果。

实验原理1.Strassen’s矩阵乘法简介Strassen’s算法是将矩阵分成了如图所示的均等的四块。

分后的每一块儿任然还是方阵。

所以可以由大问题分解成若干子问题进行解决。

为了能使子问题能够返回到原始问题。

Strassen‘s算法提出了如下的计算公式,可以用矩阵的子矩阵计算出S1-S7,然后又由S1-S7合成原始矩阵。

而S1-S7的计算又是方阵的乘法。

由此使用分治算法便可以解决问题。

2.最近点对问题(Closest Pair Problems)算法简介首先这个问题也是采用了分治的思想,将空间内的距离分成三类,分界线左边的点之间的距离,分界线右边的点之间的距离,还有分界线两边距离为D 的区域内的两点间距离。

算法具体代码1.矩阵相乘问题// Strassen.cpp : 定义控制台应用程序的入口点。

////********************************************************************************#include "stdafx.h"#include "stdlib.h"#define AM Copy(A,0,0,A.v/2)#define BM Copy(A,A.v/2,0,A.v/2)#define CM Copy(A,0,A.v/2,A.v/2)#define DM Copy(A,A.v/2,A.v/2,A.v/2)#define EM Copy(B,0,0,B.v/2)#define FM Copy(B,B.v/2,0,B.v/2)#define GM Copy(B,0,B.v/2,B.v/2)#define HM Copy(B,B.v/2,B.v/2,B.v/2)#define V 2//********************************************************************************//矩阵结构typedef struct matrix{int v;int x[16][16];}Matrix;//********************************************************************************//输入输出文件FILE *fout;FILE *fin;//********************************************************************************//矩阵打印(文件)void fPrint(Matrix A){for(int j=0;j<A.v;j++){for(int i=0;i<A.v;i++){fprintf(fout,"%d ",A.x[i][j]);}fprintf(fout,"\n");}}//******************************************************************************** //矩阵打印(屏幕)void Print(Matrix A){for(int j=0;j<A.v;j++){for(int i=0;i<A.v;i++){printf("%d ",A.x[i][j]);}printf("\n");}}//******************************************************************************** //矩阵截取Matrix Copy(Matrix X,int x,int y,int v){Matrix temp;temp.v=v;for(int i=x;i<x+v;i++){for(int j=y;j<y+v;j++){temp.x[i-x][j-y]=X.x[i][j];}}return temp;}//******************************************************************************** //矩阵相减Matrix Minus(Matrix A,Matrix B){Matrix temp;temp.v=A.v;for(int j=0;j<A.v;j++){for(int i=0;i<A.v;i++){temp.x[i][j]=A.x[i][j]-B.x[i][j];}}return temp;}//******************************************************************************** //矩阵相加Matrix Plus(Matrix A,Matrix B){Matrix temp;temp.v=A.v;for(int j=0;j<A.v;j++){for(int i=0;i<A.v;i++){temp.x[i][j]=A.x[i][j]+B.x[i][j];}}return temp;}//A: Copy(A,0,0,A.v/2)//B: Copy(A,A.v/2,0,A.v/2)//C: Copy(A,0,A.v/2,A.v/2)//D: Copy(A,A.v/2,A.v/2,A.v/2);//E: Copy(B,0,0,B.v/2)//F: Copy(B,B.v/2,0,B.v/2)//G: Copy(B,0,B.v/2,B.v/2)//H: Copy(B,B.v/2,B.v/2,B.v/2);//******************************************************************************** //矩阵合并Matrix Merge4(Matrix A,Matrix B,Matrix C,Matrix D){Matrix temp;temp.v=A.v*2;for(int i=0;i<A.v;i++){for(int j=0;j<A.v;j++){temp.x[i][j]=A.x[i][j];}}for(int i=0;i<B.v;i++){for(int j=0;j<B.v;j++){temp.x[i+B.v][j]=B.x[i][j];}}for(int i=0;i<C.v;i++){for(int j=0;j<C.v;j++){temp.x[i][j+C.v]=C.x[i][j];}}for(int i=0;i<D.v;i++){for(int j=0;j<D.v;j++){temp.x[i+D.v][j+D.v]=D.x[i][j];}}return temp;}//******************************************************************************** //矩阵相乘Matrix Mutiply(Matrix A,Matrix B){if(A.v==1 && B.v==1){A.x[0][0]=A.x[0][0]*B.x[0][0];return A;}Matrix s1,s2,s3,s4,s5,s6,s7;s1=Mutiply(AM,Minus(FM,HM));s2=Mutiply(Plus(AM,BM),HM);s3=Mutiply(Plus(CM,DM),EM);s4=Mutiply(DM,Minus(GM,EM));s5=Mutiply(Plus(AM,DM),Plus(EM,HM));s6=Mutiply(Minus(BM,DM),Plus(GM,HM));s7=Mutiply(Minus(AM,CM),Plus(EM,FM));fPrint(Plus(Plus(s5,s6),Minus(s4,s2)));fPrint(Plus(s1,s2));fPrint(Plus(s3,s4));fPrint(Minus(Minus(s1,s7),Minus(s3,s5)));returnMerge4(Plus(Plus(s5,s6),Minus(s4,s2)),Plus(s1,s2),Plus(s3,s4),Minus(Minus(s1,s7),Minus(s3,s5 )));}//********************************************************************************//数据输入Matrix RnMatrix(int v){Matrix temp;temp.v=v;for(int j=0;j<V;j++){for(int i=0;i<V;i++){fscanf(fin,"%d",&temp.x[i][j]);//1;//rand()%10;}}return temp;}//********************************************************************************//入口函数int _tmain(int argc, _TCHAR* argv[]){fout=fopen("out.txt","w");fin=fopen("in.txt","r");Matrix A,B;A.v=V;B.v=V;A=RnMatrix(V);B=RnMatrix(V);fclose(fin);Print(Mutiply(A,B));getchar();return 0;}2.最近点问题// Closest_Pair_Problems.cpp : 定义控制台应用程序的入口点。

空间最近点对的计算机算法研究

空间最近点对的计算机算法研究

将集合 S 分割 为 S 1 和 S2 两个半 平面区 域中的子 集, 递归地 分别在 S1 和 S2 上找出具有最小距离的点对 d1( p 1 , p 2 ) 和 d2 ( q1 - q2 ) , 并设 d = min{ d1 , d2 } 。用 P1 和 P 2 分 别表示 在直
线 L 左边 和右边 与其距离 在 d 范 围的点 构成的 两个垂直 长 条平面区域, P 1 : { p | | m- x (p ) | # d ∃p P 1 } ; P 2 : { q| | x ( q) - m| # d ∃q P2 } 。 分析可以知道, S 中的最近点对的距离 或者是 d , 或者是 某个 { p , q} 点对的距离, 其中 p P1 , q P 2 。如果{ p , q} 是 S 中的 最近点对, 则必有 distance( p , q) < d。对于 P 1 中的任意 一点 p , 满足这个条件的 P 2 中的点 q 一定落在一个 d % 2d 的 矩形 R 中; 可以证明在矩 形 R 中 最多 只有 6 个 S 中 的点 作为 P1 中点 p 的最近点对的候选者。 因此很 容易在 O ( n) 时间 内进 行处理。在进行分 治处 理之 前需 要对 集合 S 中 点的 坐标 采 用预排序技术, 预先将 n 个点依 次按照 坐标排 序。分治算 法 中只对排好序的序列做 一次线性扫描, 即可完成合并。因此, 平面最近点对算法耗费的计算时 间 T ( n) 也满足递归方程, 可 以在 O( n* log n) 时间内完成。
∋ 233 ∋
p 2 } 和{ q1 , 并设 d= min { d1 , d2} 。如果集合 S 中的最近点对的距离小于 d , 则这两个 点 p 3 、q3 必定分别属于子集 S1 和 S2 。即 S 中 的最近点对的 距离或者是 d , 或者是某个{ p 3 , q3 } 点对的距离, 其中 p 3 S1 , q3 S2 , 如图 1 所示。

最小距离问题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=closestPoint(s,low,mid,rec); temp1[0]=rec[0]; temp1[1]=rec[1]; d2=closestPoint(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--) 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=j+1;j<index;i++){ if((P[j].y-P[i].y)>=d) break; else { d3=Distance(P[i],P[j]); //升序排列 //点集合 p2 //点集合 p1

平面最近点对问题(分治)

平⾯最近点对问题(分治)平⾯最近点对问题是指:在给出的同⼀个平⾯内的所有点的坐标,然后找出这些点中最近的两个点的距离.⽅法1:穷举1)算法描述:已知集合S中有n个点,⼀共可以组成n(n-1)/2对点对,蛮⼒法就是对这n(n-1)/2对点对逐对进⾏距离计算,通过循环求得点集中的最近点对2)算法时间复杂度:算法⼀共要执⾏ n(n-1)/2次循环,因此算法复杂度为O(n2)代码实现:利⽤两个for循环可实现所有点的配对,每次配对算出距离然后更新最短距离.for (i=0 ; i < n ;i ++){for(j= i+1 ; j<n ;j ++){点i与点j的配对}}⽅法2:分治1) 把它分成两个或多个更⼩的问题;2) 分别解决每个⼩问题;3) 把各⼩问题的解答组合起来,即可得到原问题的解答。

⼩问题通常与原问题相似,可以递归地使⽤分⽽治之策略来解决。

在这⾥介绍⼀种时间复杂度为O(nlognlogn)的算法。

其实,这⾥⽤到了分治的思想。

将所给平⾯上n个点的集合S分成两个⼦集S1和S2,每个⼦集中约有n/2个点。

然后在每个⼦集中递归地求最接近的点对。

在这⾥,⼀个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。

如果这两个点分别在S1和S2中,问题就变得复杂了。

为了使问题变得简单,⾸先考虑⼀维的情形。

此时,S中的n个点退化为x轴上的n个实数x1,x2,...,xn。

最接近点对即为这n个实数中相差最⼩的两个实数。

显然可以先将点排好序,然后线性扫描就可以了。

但我们为了便于推⼴到⼆维的情形,尝试⽤分治法解决这个问题。

假设我们⽤m点将S分为S1和S2两个集合,这样⼀来,对于所有的p(S1中的点)和q(S2中的点),有p<q。

递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设 d = min{ |p1-p2| , |q1-q2| } 由此易知,S中最接近点对或者是{p1,p2},或者是{q1,q2},或者是某个{q3,p3},如下图所⽰。

最接近点对问题

一、最接近点对问题(一维)1、最接近点对问题(一维)最接近点对问题:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。

此时S中的n个点退化为x轴上的n个实数x1,x2,..,x n。

最接近点对即为这n 个实数中相差最小的2个实数。

2、分析将所给的平面上n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,·然后在每个子集中递归地求其最接近的点对。

S1和S2的最接近点对未必就是S的最接近点对,如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。

但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n2/4次计算和比较才能确定S的最接近点对。

因此,依此思路,合并步骤耗时为O(n2)。

整个算法所需计算时间T(n)应满足:T(n)=2T(n/2)+O(n2)它的解为T(n)=O(n2)3、伪代码随机Randomfloat Random(){float result=rand()%10000;return result*0.01;}返回最大、最小float Max OR Min(float s[],int p,int q)//返回s[]中的最大值{float s_max(s_min)=s[p];for(int i=p+1;i<=q;i++)if(s_max<s[i])s_max=s[i]; ORif(s_min>s[i])s_min=s[i];return s_max(s_min)}主要函数Cpair Cpair1(float s[],int n){Cpair out_p_d={99999,0,0};if(n<2) return out_p_d;float m1=Max(s,0,n-1),m2=Min(s,0,n-1);float m=(m1+m2)/2;//找出点集中的中位数int j=0,k=0;//将点集中的各元素按与m的大小关系分组float s1[M],s2[M];for(int i=0;i<n;i++){if(s[i]<=m) {s1[j]=s[i];j++;}else {s2[k]=s[i];k++;}}Cpair d1=Cpair1(s1,j),d2=Cpair1(s2,k);//递归float p=Max(s1,0,j-1),q=Min(s2,0,k-1);//返回s[]中的具有最近距离的点对及其距离if(d1.d<d2.d){if((q-p)<d1.d){out_p_d.d=(q-p);out_p_d.d1=q;out_p_d.d2=p;return out_p_d;}else return d1;}else{if((q-p)<d2.d){out_p_d.d=(q-p);out_p_d.d1=q;out_p_d.d2=p;return out_p_d;}else return d2;}}4、程序实现#include<time.h>#include <iostream>using namespace std;const int M=50;struct Cpair{float d;float d1,d2;};float Random();int input(float s[],int number_used);float Max(float s[],int p,int q);float Min(float s[],int p,int q);Cpair Cpair1(float s[],int n);void main(){srand((unsigned)time(NULL));int number_used,m;float s[M];Cpair d;m=input(s,number_used);d=Cpair1(s,m);cout<<endl<<"the closest pair is ("<<d.d1<<","<<d.d2<<")";cout<<endl<<"the min distance is "<<d.d<<endl;}float Random(){float result=rand()%10000;return result*0.01;}int input(float s[],int number_used){cout<<"input the number ";cin>>number_used;cout<<"the random number are ";for(int i=1;i<=number_used;i++){s[i]=Random();cout<<s[i]<<" ";}return number_used;}float Max(float s[],int p,int q)//返回s[]中的最大值{float s_max=s[p];for(int i=p+1;i<=q;i++)if(s_max<s[i])s_max=s[i];return s_max;}float Min(float s[],int p,int q)//返回s[]中的最小值{float s_min=s[p];for(int i=p+1;i<=q;i++)if(s_min>s[i])s_min=s[i];return s_min;}//返回s[]中的具有最近距离的点对及其距离Cpair Cpair1(float s[],int n){Cpair out_p_d={99999,0,0};if(n<2) return out_p_d;float m1=Max(s,0,n-1),m2=Min(s,0,n-1);float m=(m1+m2)/2;//找出点集中的中位数int j=0,k=0;//将点集中的各元素按与m的大小关系分组float s1[M],s2[M];for(int i=0;i<n;i++){if(s[i]<=m) {s1[j]=s[i];j++;}else {s2[k]=s[i];k++;}}Cpair d1=Cpair1(s1,j),d2=Cpair1(s2,k);//递归float p=Max(s1,0,j-1),q=Min(s2,0,k-1);//返回s[]中的具有最近距离的点对及其距离if(d1.d<d2.d){if((q-p)<d1.d){out_p_d.d=(q-p);out_p_d.d1=q;out_p_d.d2=p;return out_p_d;}else return d1;}{if((q-p)<d2.d){out_p_d.d=(q-p);out_p_d.d1=q;out_p_d.d2=p;return out_p_d;}else return d2;}}运行情况:二、最接近点对问题(二维)1、最接近点对问题(二维)二维时S中的点为平面上的点,它们都有2个坐标值x和y。

最近对问题-递归与分治算法

实验1 递归与分治算法一,实验目的和要求(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。

(3)分别用蛮力法和分治法求解最近对问题;(4)分析算法的时间性能,设计实验程序验证分析结论。

二,实验内容设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

三,实验环境Turbo C 或VC++四,实验学时2学时,必做实验五,数据结构与算法#include<iostream.h>#include<cmath>#define TRUE 1#define FALSE 0typedef struct Node{double x;double y;}Node; //坐标typedef struct List{Node* data; //点int count; //点的个数}List;typedef struct CloseNodeNode a;Node b; //计算距离的两个点double space; //距离平方}CloseNode;int n; //点的数目//输入各点到List中void create(List &L){cout<<"请输入平面上点的数目:\n";cin>>n;L.count=n;L.data = new Node[L.count]; //动态空间分配cout<<"输入各点坐标 :x_y):"<<endl;for(int i=0;i<L.count;++i)cin>>L.data[i].x>>L.data[i].y;}//求距离的平方double square(Node a,Node b){return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));}//蛮力法void BruteForce(const List &L,CloseNode &cnode,int begin,int end) {for(int i=begin;i<=end;++i){for(int j=i+1;j<=end;++j){double space=square(L.data[i],L.data[j]);if(space<cnode.space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}}}//冒泡排序void BubbleSort(Node r[],int length)int change,n;n=length;change=TRUE;double b,c;for(int i=0;i<n-1&&change;++i){change=FALSE;for(int j=0;j<n-i-1;++j){if(r[j].x>r[j+1].x){b=r[j].x;c=r[j].y;r[j].x=r[j+1].x;r[j].y=r[j+1].y;r[j+1].x=b;r[j+1].y=c;change=TRUE;}}}}//分治法中先将坐标按X轴从小到大的顺序排列void paixu(List L){BubbleSort(L.data,L.count); //调用冒泡排序}//左右各距中线d的区域的最近对算法void middle(const List & L,CloseNode &cnode,int mid,double midX){int i,j; //分别表示中线左边,右边的点double d=sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)) //在左边的d区域内{j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count) //在右边的d区域内 {if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d)) //判断纵坐标是否在左边某固定点的2d区域内continue;double space = square(L.data[i],L.data[j]);if(cnode.space>space) //在满足条件的区域内依次判断{cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}--i;}}//分治法求最近对void DivideConquer(const List &L,CloseNode &closenode,int begin,int end){if(begin!=end){int mid = (begin+end)/2; //排列后的中间的那个点double midX = L.data[mid].x;DivideConquer(L,closenode,begin,mid); //继续在左半边用分治法求最近对DivideConquer(L,closenode,mid+1,end); //继续在右半边用分治法求最近对middle(L,closenode,mid,midX); //判断左右各距中线d的区域,是否有最近对}}void main(){//初始化List list;CloseNode closenode;closenode.space = 10000; //最近点的距离create(list); //输入各点到NList中cout<<"各点坐标为:"<<endl;for(int i=0;i<list.count;++i)cout<<"X="<<list.data[i].x<<" Y="<<list.data[i].y<<"\n";BruteForce(list,closenode,0,list.count-1);cout<<"用蛮力法求最近对:"<<endl;cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<endl<<endl;cout<<"用分治法求最近对:"<<endl;paixu(list);cout<<"经过排序后的各点:"<<endl;for(int j=0;j<list.count;++j)cout<<"X="<<list.data[j].x<<" Y="<<list.data[j].y<<"\n";DivideConquer(list,closenode,0,list.count-1);cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为:}六,核心源代码//左右各距中线d的区域的最近对算法void middle(const List & L,CloseNode &cnode,int mid,double midX){int i,j; //分别表示中线左边,右边的点double d=sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)) //在左边的d区域内{j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count) //在右边的d区域内 {if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d)) //判断纵坐标是否在左边某固定点的2d区域内continue;double space = square(L.data[i],L.data[j]);if(cnode.space>space) //在满足条件的区域内依次判断{cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}--i;}}//分治法求最近对void DivideConquer(const List &L,CloseNode &closenode,int begin,int end){if(begin!=end){int mid = (begin+end)/2; //排列后的中间的那个点double midX = L.data[mid].x;DivideConquer(L,closenode,begin,mid); //继续在左半边用分治法求最近对DivideConquer(L,closenode,mid+1,end); //继续在右半边用分治法求最近对middle(L,closenode,mid,midX); //判断左右各距中线d的区域,是否有最近对}}七,实验结果八,实验体会通过这次实验,我深刻了解到分治法的实用性,有效性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档