分治法最近对问题文档格式.doc
- 文档编号:13165076
- 上传时间:2022-10-07
- 格式:DOC
- 页数:5
- 大小:89KB
分治法最近对问题文档格式.doc
《分治法最近对问题文档格式.doc》由会员分享,可在线阅读,更多相关《分治法最近对问题文档格式.doc(5页珍藏版)》请在冰豆网上搜索。
所以复杂度就是求平方,求执行次数为:
;
即时间复杂度为。
2.分治法求最近对问题:
1)基本思想:
用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。
可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。
则基本过程为:
找一条中垂线(坐位集合坐标的中位数)把个元素分成左右两部分元素,然后分别求得两边的最短距离,,然后取两者中的最小者记为,在中线两边分别取的距离,记录该距离范围内点的个数,中线左边有个元素,右边有个元素,分别将两边的点按y坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于的点,更新最短距离,直到循环结束,即可求出最短距离。
应用分治法求解含有个点的最近对问题,其时间复杂性可由递推式表示:
。
由以上分析:
合并子问题的解的时间。
进而可得分治法求最近对问题的时间复杂度为:
三、源程序及注释:
#include<
iostream>
cstring>
cmath>
algorithm>
time.h>
usingnamespacestd;
#defineeps1e-8
#defineMAXN10000000
#defineN5000
structPoint
{
doublex,y;
};
PointS[N*2],S1[N],S2[N],P1[N],P2[N];
doubleDistance(Pointa,Pointb)
returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
intcmp1(Pointa,Pointb)
returna.x<
b.x;
intcmp2(Pointa,Pointb)
returna.y<
b.y;
doublemin(doublea,doubleb)
returna>
b?
b:
a;
//分治法求最近对问题
doubleClosestPoints1(PointS[],intn)
inti,j,m;
if(n<
2)returnMAXN;
else
{
doubled0=MAXN;
doubled,d1,d2;
intk1=0;
intk2=0;
intj1=0;
intj2=0;
sort(S,S+n,cmp1);
Pointp=S[n/2];
m=p.x;
//m=S中各点x坐标的中位数
for(i=0;
i<
(n+1)/2;
i++)
{
S1[j1].x=S[i].x;
S1[j1].y=S[i].y;
j1++;
} //构造S1中点的坐标小于m
for(i=(n+1)/2;
n;
i++)
S2[j2].x=S[i].x;
S2[j2].y=S[i].y;
j2++;
} //构造S2中点的坐标大于m
d1=ClosestPoints1(S1,j1);
d2=ClosestPoints1(S2,j2);
d=min(d1,d2);
for(i=0;
j1;
if(m-S1[i].x<
d)
{
P1[k1].x=S1[i].x;
P1[k1].y=S1[i].y;
k1++;
} //构造P1为S1中点的坐标与m的距离小于d的点集
if(S2[i].x-m<
P2[k2].x=S2[i].x;
P2[k2].y=S2[i].y;
k2++;
} //构造P2为S2中点的坐标与m的距离小于d的点集
sort(P1,P1+k1,cmp2);
//将P1中的点按y坐标升序排列
sort(P2,P2+k2,cmp2);
//将P2中的点按y坐标升序排列
k1;
for(j=0;
j<
k2;
j++)
doubleans=Distance(P1[i],P2[j]);
d0=min(d0,ans);
//求最小距离
}
}
returnmin(d0,d);
}
//蛮力法求最近对问题
doubleClosestPoints2(PointS[],intn)
doubled0=MAXN;
for(inti=0;
{
for(intj=i+1;
{
doubled=Distance(S[i],S[j]);
if(d<
d0)
d0=d;
}
}
returnd0;
//测试两种算法
intmain()
intn=5000;
inti;
srand((unsigned)time(NULL));
for(i=0;
S[i].x=rand()/(double)(RAND_MAX/10000);
S[i].y=rand()/(double)(RAND_MAX/10000);
}//产生随机点集
clock_tstart1,end1,start2,end2;
start1=clock();
doubled1=ClosestPoints1(S,n);
end1=clock();
start2=clock();
doubled2=ClosestPoints2(S,n);
end2=clock();
cout<
<
"
分治法求最近对问题运行时间及结果"
endl <
double(end1-start1)/CLOCKS_PER_SEC<
"
d1<
endl;
蛮力法求最近对问题运行时间及结果"
double(end2-start2)/CLOCKS_PER_SEC<
d2<
return0;
四、运行输出结果:
比较运行结果,得出结论,分治法与蛮力法所求结果相同,从运行时间上来讲分治法运行远远快于蛮力法。
五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:
1.课本只给出了伪代码,具体的实验要靠自己动手上机反复实验才能完成。
要通过赋简单值法来初步检验程序的是否正确,再以相同数据检验两种方法的运行结果是否一致来进一步判断程序是否正确,同时使得两种算法的比较更加公平,实验更有可信度。
2.要比较分治法和蛮力法求最近对问题的时间复杂度,就要两者各自的运行时间。
为此,必须要有大量数据,便利用了rand()函数产生大量随机数,还增加了实验可信度。
3.不要太迷信课本。
其中课本上伪代码的函数返回值类型定义为int型,使得赋简单值时运行结果始终为0,注意到这一点,将int改为double才得到了较准确的运行结果。
所以,编程是要自己多动脑思考,才能真正解决问题。
5
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 分治 最近 问题