中科大软院算法导论最近点对算法_C++
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
l1=divide(left,l);
l2=divide(l+1,right);
if (l1<l2)
{
Min=l1;Fra Baidu bibliotek
//cout<<"两半面最短距离是:"<<min;
} else {
Min=l2; //cout<<"两半面最短距离是:"<<min; } ///////////////////得到右半块元素数 R //cout<<"min="<<min<<endl; for (i=l+1;i<N;i++) { if (x[i]-x[l]<=Min)
double lengthf(int x1,int y1,int x2,int y2) {
return sqrt(square(x1-x2)+square(y1-y2)); }
//////////////////////////////////求两者中最小者////////////////////// double min(double a,double b) {
分治法是把一个大的问题划分成相似的小问题,采用递归的思想。找中线把 n 个元 素分成左右两部分元素分别求得两边的最短距离,然后取两者中的最小者记为 l,在中线两 边分别取 l 的距离,记录该距离范围内点的个数,中线左边有 L 个元素,右边有 R 个元素, 求左边元素到右边元素的距离看其是否小于之前记录的最短距离,小则记录下来,此时的右
边元素只取 y 值和左边元素 y 值距离小于 l 的(减少循环次数)。循环结束即可找到最小的 距离。
2.程序代码:
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cmath>
using std::cout;
using std::endl;
int rem1,rem2,l;
//记录获得最短距离对应的两个点
//int il,jl,ir,jr;
int i,j;
int R,L;
R=L=0;
//记录划分小区域后的左半块和右半
块个有多少元素
l1=l2=Min=100;
l=(right-left+1)/2-1;
//中线位置
///////////////////////////////////////////////////
cout<<record[i]<<' '; cout<<endl; }
//得到 x 排序后对应的原 y 的坐标
///////////////////////////穷举法找最小点对/////////////////////////////// double exhaustion() {
int i,j,k1,k2; double num; double length; num=10000; k1=k2=-1; for (j=0;j<N-1;j++) {
for (i=j+1;i<N;i++) {
length=lengthf(x[i],y[i],x[j],y[j]); if (length<num) {
num=length; k1=i; k2=j; } } } cout<<"平面数组最短距离是:"<<endl; cout<<"min="<<num<<endl; cout<<"对应数组下标及点坐标为:"<<endl; cout<<"i="<<k1<<','<<k2<<endl;
cout<<"(x1,y1)="<<'('<<x[k1]<<','<<y[k1]<<')'<<endl<<"(x2,y2)="<<'('<<x[k2]<<','<<y[k2]<<')' <<endl;
return num;
} ////////////////////////////////////分治法/////////////////////////////// /*************************************************************************/
#define N 5
int x[N],y[N],record[N];
//产生原始点数据,x 坐标放在 x[]中,y 坐标放在 y[]中。
double Min;
//////////////////////////产生随机数组/////////////////////////////
void randnum()
i=j; while (i>=0&&A[i]<A[i-1])
{ swap(A[i],A[i-1]); swap(record[i-1],record[i]); i--;
} } cout<<"排序后的元素数组:"<<endl; for (i=0;i<N;i++)
cout<<A[i]<<' '; cout<<endl; for (i=0;i<N;i++)
3.实验数据及实验结果:
实验数据: 随机产生的五个点坐标分别为:(1,3),(4,2),(3,0),(2,0),(0,3) 实验结果:用蛮力法得到平面数组最短距离为:min=1
用分治法得到平面数组最短距离为:min=1
4.实验总结:
从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原 来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束, 一般都有元素个数的限制。并且通过这次试验巩固了排序算法。
double merge(int left,int right) {
double mlength; if (right==left)
mlength=10e-6; if (right==left+1)
mlength=lengthf(x[right],y[record[right]],x[left],y[record[left]]); if (right-left==2)
int temp=a; a=b; b=temp; }
///////////////////////////////求平方/////////////////////////////////// int square(int x) {
return x*x; }
/////////////////////////////////////求两点之间距离////////////////////
if (L!=0&&R!=0) {
for (i=l-L+1;i<=l;i++) for (j=l+1;j<=l+R;j++) { if (y[record[j]]-y[record[i]]<Min||-Min<y[record[j]]-y[record[i]]) { mi=lengthf(x[i],y[record[i]],x[j],y[record[j]]); if (mi<Min) { Min=mi; rem1=i; rem2=j; } } }
//三个点时求最大值 return mlength; }
double divide(int left,int right)
{
if (right-left<=2)
{
Min=merge(left,right);
}
else
{
double l1,l2,mi;
//l1 记录划分区域后左半面最小距离,l2
记录右半面最小距离,min 为两者中较小者,m 为全部中的最小者
实验四 求最近点对算法
1.算法设计思路:
设共有 n 个点,找其中距离最近的两点及其距离。 (1)蛮力法: 蛮力法的思路是把所有点之间距离比较找出中间最小的。先假设最短距离是第一个
元素和第二个元素的距离,然后求第一个元素与其后的(n-1)个元素各自的距离,若比之 前记录的最短距离小则记录当前值···求第 i 个元素与其后的(n-i)个元素各自的距离,记 录之前所得到的所有距离中的最小值,直到计算到第(n-1)个元素与第 n 个元素的距离, 此时记录的距离即为这 n 个元素中的最短距离。 (2)分治法:
//两个点时求最小值
mlength=min(min(lengthf(x[right-1],y[record[right-1]],x[left],y[record[left]]),lengthf(x[right],y[re cord[right]],x[left+1],y[record[left+1]])),lengthf(x[right],y[record[right]],x[left],y[record[left]]));
{
int i;
srand(time(0));
for (i=0;i<N;i++)
{
x[i]=rand()%N;
cout<<x[i]<<' ';
}
cout<<endl;
for (i=0;i<N;i++)
{
y[i]=rand()%N;
cout<<y[i]<<' ';
} cout<<endl; }
//////////////////////////////交换数组元素/////////////////////////// void swap(int & a, int & b) {
if (a>=b) return b;
else return a;
} ////////////////////////////对平面数组排序//////////////////////////// void sort(int A[]) {
int i,j; for (i=0;i<N;i++)
record[i]=i; for (j=1;j<N;j++) {
// cout<<"min="<<min<<endl; //cout<<"rem1="<<rem1<<endl<<"rem2="<<rem2<<endl;
}
} return Min; } /***********************************************************************/ //////////////////////////////////主函数/////////////////////////////////// int main() { //double a; randnum(); cout<<"***************************遍历法*************************"<<endl; exhaustion(); cout<<"***************************分治法*************************"<<endl; sort(x); divide(0,N-1); cout<<"元素组中最短距离为:"<<endl; cout<<"min="<<Min<<endl; return 0; }
R++; else break; } //cout<<"R="<<R<<endl; /////////////////////得到左半块元素数 L for (i=l;i>=0;i--) { if (x[l]-x[i]<=Min)
L++; else break; } //cout<<"L="<<L<<endl;