分治法

4 2

5 7 1 2

6 3 4 | 2 | 5 |

7 | 1 | 2 | 6 | 3

4 2

5 7 | 1 2

6 3 2 4 | 5

7 | 1 2 | 3 6

4 2 |

5 7 | 1 2 |

6 3 2 4 5

7 | 1 2 3 6

4 | 2 |

5 | 7 | 1 | 2 |

6 | 3 1 2 2 3 4 5 6 7

这种自底向上分治策略的编程模式如下:

如果问题规模足够小,直接求解,否则

单纯地分解原问题为规模更小的子问题,并持续这种分解;

执行求解动作,将子问题的解合并为原问题的解。

由于在自底向上的归并过程中,每一层需要进行i组n/i次比较,而且由于进行的是单纯的对称分解,总的层数总是lg n,因此,归并排序在各种情况下的时间代价都是Θ(n lg n)。试想,能够加大分组的力度,即每次将原问题分解为大于2的子问题,来降低运行时间?

归并排序算法的代码如下:

/*

* p: 左数组第一个元素下标

* q: 左数组最后一个元素下标

* r: 右数组最后一个元素下标

*/

void merge_no_sentinel(int *array, int p, int q, int r)

{

int n1, n2, i, j, k;

int *left=NULL, *right=NULL;

n1 = q-p+1;

n2 = r-q;

left = (int *)malloc(sizeof(int)*(n1)); right = (int *)malloc(sizeof(int)*(n2));

for(i=0; i

{

left[i] = array[p+i];

}

for(j=0; j

{

right[j] = array[q+1+j];

}

i = j = 0;

k = p;

while(i

{

if(left[i] <= right[j])

{

array[k++] = left[i++];

}

else

{

array[k++] = right[j++];

}

}

for(; i

{

array[k++] = left[i];

}

for(; j

{

array[k++] = right[j];

}

free(left);

free(right);

left = NULL;

right = NULL;

}

void merge_sort(int *array, int p, int r)

{

int q;

if(p < r)

{

q = (int)((p+r)/2);

merge_sort(array, p, q);

merge_sort(array, q+1, r);

merge_no_sentinel(array, p, q, r);

}

4 2

5 7 1 2

6 | 3

2 1 2 |

3 | 7

4

5 6

1 |

2 | 2 |

3 |

4

5 |

6 | 7

1 |

2 | 2 |

3 |

4 |

5 |

6 | 7

这种自顶向下分治策略的编程模式如下:

如果问题规模足够小,直接求解,否则

执行求解动作,将原问题分解为规模更小的子问题;

递归地求解每个子问题;

因为求解动作在分解之前进行,在对每个子问题求解之后,不需要合并过程。

快速排序的运行时间与分解是否对称有关,而后者又与选择了哪一个元素来进行划分有关。如果划分是对称的,则运行时间与归并排序相同,为Θ(n lg n)。如果每次分解都形成规模为n-1和0的两个子问题,快速排序的运行时间将变为Θ(n2)。快速排序的平均情况运行时间与其最佳情况相同,为Θ(n lg n)。

快速排序算法的代码如下:

void swap(int *a, int *b)

{

int temp;

temp = *a;

*a = *b;

*b = temp;

}

/*

* p: 数组第一个元素的下标

* r: 数组最后一个元素的下标

* 返回值为分组后主元的下标

*/

int partition(int *array, int p, int r)

{

int i, j, pivot;

pivot = array[r];

i = p-1;

for(j=p; j<=r-1; j++)

{

if(array[j] <= pivot)

{

i++;

swap(&array[i], &array[j]);

}

}

swap(&array[i+1], &array[r]);

return i+1;

}

void quick_sort(int *array, int p, int r)

{

int q;

if(p < r)

{

q = partition(array, p, r);

quick_sort(array, p, q-1);

quick_sort(array, q+1, r);

}

}

通常,我们可以向一个算法中加入随机化成分(参考第5章内容),以便对于所有输入,它均能获得较好

的平均情况性能。将这种方法用于快速排序时,不是始终采用A[r]作为主元,而是从子数组A[p..r]中随机

选择一个元素,即将A[r]与从A[p..r]中随机选出的一个元素交换。

#include

#include

int randomized_partition(int *array, int p, int r)

{

int i;

srand(time(NULL));

i = rand()%(r-p)+p;

swap(&array[i], &array[r]);

return partition(array, p, r);

}

void randomized_quick_sort(int *array, int p, int r)

{

int q;

if(p < r)

{

q = randomized_partition(array, p, r);

randomized_quick_sort(array, p, q-1);

randomized_quick_sort(array, q+1, r);

}

}

0007算法笔记——【分治法】最接近点对问题

问题场景:在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看待,则具有最大碰撞危险的2架飞机,就是这个空间中最接近的一对点。这类问题是计算几何学中研究的基本问题之一。 问题描述:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。严格地说,最接近点对可能多于1对。为了简单起见,这里只限于找其中的一对。 1、一维最接近点对问题 算法思路: 这个问题很容易理解,似乎也不难解决。我们只要将每一点与其他n-1个点的距离算出,找出达到最小距离的两个点即可。然而,这样做效率太低,需要O(n^2)的计算时间。在问题的计算复杂性中我们可以看到,该问题的计算时间下界为Ω(nlogn)。这个下界引导我们去找问题的一个θ(nlogn)算法。采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S 的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n^2/4次计算和比较才能确定S的最接近点对。因此,依此思路,合并步骤耗时为O(n^2)。整个算法所需计算时间T(n)应满足:T(n)=2T(n/2)+O(n^2)。它的解为T(n)=O(n^2),即与合并步骤的耗时同阶,这不比用穷举的方法好。从解递归方程的套用公式法,我们看到问题出在合并步骤耗时太多。这启发我们把注意力放在合并步骤上。 设S中的n个点为x轴上的n个实数x1,x2,..,xn。最接近点对即为这n个实数中相差最小的2个实数。我们显然可以先将x1,x2,..,xn排好序,然后,用一次线性扫描就可以找出最接近点对。这种方法主要计算时间花在排序上,在排序算法已经证明,时间复杂度为O(nlogn)。然而这种方法无法直接推广到二维的情形。因此,对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。假设我们用x轴上某个点m将S划分为2个子集S1和S2,使得S1={x∈S|x≤m};S2={x∈S|x>m}。这样一来,对于所有p∈S1和q∈S2有p

分别用蛮力法、分治法、减治法实现a的N次方

《算法设计与分析》实验报告一 学号:姓名: 日期: 2012.11.5 得分: 一、实验内容: 分别用蛮力法、分治法、减治法实现a^n。 二、实验要求: 完成试验报告、给出对此结果。 为防止大数溢出,可以用1^n来测试在n比较大是的三种算法运行情况。 四、源程序及注释: #include #include using namespace std; //蛮力法求a的n次方 int Power1(int a,int n) { int as=1; for(int i=0;i

} int main() { int a=1; int n=10000; LARGE_INTEGER start1,end1,start2,end2,start3,end3,f; QueryPerformanceFrequency(&f); QueryPerformanceCounter(&start1) ; int p1=Power1(a,n); QueryPerformanceCounter(&end1); QueryPerformanceCounter(&start2) ; int p2=Power2(a,n); QueryPerformanceCounter(&end2); QueryPerformanceCounter(&start3) ; int p3=Power3(a,n); QueryPerformanceCounter(&end3); cout<<"a="<

分治法实验报告一

宁波工程学院电信学院计算机系 实验报告 课程名称:算法设计与分析实验项目:用分治法算法解 最接近点对问题 指导教师:崔迪 实验位置:软件工程实验室姓名: 班级: 学号: 日期: 2016/10/12 一、实验目的 通过上机实验,要求掌握分治法算法的问题描述、算法设计思想、程序设 计和算法复杂性分析等。 二、实验环境: Eclipse 三、实验内容:用分治法解最接近点对问题 (1)问题描述 给定平面S上n个点,找其中的一对点,使得在n(n-1)/2 个点对中,该 点对的距离最小。 (2)算法设计思想 1. n较小时直接求 (n=2). 2.将S上的n个点分成大致相等的2个子集S1和S2 3.分别求S1和S2中的最接近点对 4.求一点在S1、另一点在S2中的最近点对 5.从上述三对点中找距离最近的一对.

(3)程序设计(程序清单及说明) package closestpair; import java.util.Arrays; import https://www.360docs.net/doc/159125884.html,parator; import java.util.Random; import java.util.Scanner; //定义坐标点 class Point { double x; double y; public Point(double x, double y) { this.x = x; this.y = y; } } // 根据x坐标排序 class MyComparatorX implements Comparator { @Override public int compare(Point p1, Point p2) { if (p1.x < p2.x) { return -1; } else if (p1.x > p2.x) { return 1; } else { return 0; } } } // 根据Y坐标排序 class MyComparatorY implements Comparator { @Override public int compare(Point p1, Point p2) { if (p1.y < p2.y) { return -1; } else if (p1.y > p2.y) { return 1; } else {

最接近点对问题实验报告

最接近点对问题 一.实验目的: 1.理解算法设计的基本步骤及各步的主要内容、基本要求; 2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题; 3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。 二.实验内容: 1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。 2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。 3.对实验结果进行分析。 三.实验操作: 1.最接近点对查找的思想: 首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。由于距离最近的两个点可能在不同的区域中,需要进一步判断。 选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。 2.取中位数: 为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。 代码实现: template void Merge(Type c[],Type d[],int l,int m,int r){ int i = l,j = m + 1,k = l; while((i<=m)&&(j<=r)){ if(c[i]<=c[j]) d[k++] = c[i++]; else d[k++] = c[j++]; } if(i>m) { for(int q=j; q<=r; q++) d[k++] = c[q]; } else{ for(int q=i; q<=m; q++) d[k++] = c[q]; } } template void MergeSort(Type a[],Type b[],int left,int right){ if(left

分治法

分治法 【摘要】:分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。本文主要叙述了分治法的设计思想及与之有关的递归思想,了解使用分治法解决问题的过程。 【关键词】:分治法分解算法递归二分搜索 Partition Method (Junna Wei) 【abstract 】: the partition method can explain to popular: decomposition, put a slice of territory is decomposed into several pieces of small, then pieces of land occupation of conquest, the decomposition can be different political factions or something, then let them each other alienation. This paper mainly describes the design idea of the partition method and recursive thinking, related to understand the process of solving the problem using the partition method. 【key words 】: partition method decomposition algorithm recursive Binary search 1.引论

算法实验四_空间最近点对算法

一、算法分析 该算法的问题描述为:给定二维平面上的点集,求解距离最近的两个点,并计算出两点间的距离。 解决问题最初的思路为穷举法。对所有两点间的组合计算其距离。然后对其进行比较,找出最小值即可。不过这样做的缺点是时间复杂度和空间复杂度十分庞大,消耗巨量资源。如有n个点的平面上,计算的复杂度能达到n*n。因此设计出一个高效的算法来代替穷举法是有现实意义的。 在思考问题的过程中,可以考虑使用分治法的思想,以x,y中x坐标作为划分区间的标准。将平面点集一分为二。求解其中的最小点对。由此产生的问题为划分点附近两个区间中两点的距离可能小于各自区间中的最小值,产生了纰漏。因此在在分治的过程中,加入分界线附近的点对最小值求解函数。分界线区域内区间的选取标准为d。其中d为左半区间和右半区间的最小值中的较小值。在具体实现中,首先建立一个空数组存放按y坐标排序的点集,判断两个相邻点之间的y坐标差值,若大于d,则两点间距离一定大于d,可以直接跳过,继续判断下一个点对。若小于d,则继续计算两点间的实际距离,若大于d,则跳过,小于d,将最小值更新为该点对距离。 二、算法实现 该算法的具体实现使用了两种求解方法,穷举法和分治法。其中,穷举法用于判断最近点对算法实现结果的正确性。 算法使用的数据结构为数组,其中为了简单起见,将x轴坐标与y轴坐标分别存入两个数组,并新建一个数组record[],记录数组y的元素下标,用于绑定x坐标对应的y坐标。 在设计过程中使用到了比较排序算法,用于对x及y坐标排序,这并不增加其时间复杂度。因此是可行的。 在分治算法中,设置划分区间的下限为3,即当区间内元素个数小于等于3时,不再使用分治。在该设定下分为三种情况,元素数为1时,Min设为无穷。元素数为2时,计算两点间距离并返回。元素数为3时,一共计算三次距离,并取其最小值。

最近点对分治法

假设在一片金属上钻n 个大小一样的洞,如果洞太近,金属可能会断。若知道任意两个洞的最小距离,可估计金属断裂的概率。这种最小距离问题实际上也就是距离最近的点对问题。 如果不用分治法,问题非常容易解决。也就是蛮力法。 代码如下: #include #include typedef struct TYPE { double x, y; } Point; float dist(Point a,Point b) { return (float)sqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } float nearest(Point* points, int n) { float temp,near1=10000; int i,j; if(n==1) { printf("不可能"); return 0; } else{ for(i=0; itemp)?temp:near1; } } return near1; } } int main()

{ int n, i; double d; printf("输入点的个数:"); scanf("%d", &n); Point a[10000]; while (n) { for (i = 0; i < n; i++) scanf("%lf%lf", &(a[i].x), &(a[i].y)); d = nearest(a,n); printf("%.2lf\n", d); scanf("%d", &n); } return 0; } 但是本题是用分治法,我也参考了网上很多资料,他们要求对纵坐标进行排序,可能是为了对求右边的问题的点扫描用for 循环,但我发现那算法就不对,但愿是我的还没有完全明白按纵坐标排序的原因, 我参考的资料: https://www.360docs.net/doc/159125884.html,/p-198711591.html?qq-pf-to=pcqq.c2c 代码如下: #include #include #include

最近点对问题

最近点对问题 I.一维问题: 一、问题描述和分析 最近点对问题的提法是:给定平面上n个点,找其中的一对点,使得在n个点组成的所有点对中,该点对间的距离最小。 严格的讲,最接近点对可能多于1对,为简单起见,只找其中的1对作为问题的解。简单的说,只要将每一点与其它n-1个点的距离算出,找出达到最小距离的2点即可。但这样效率太低,故想到分治法来解决这个问题。也就是说,将所给的平面上n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点。然后在每个子集中递归的求其最接近的点对。这里,关键问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决,但如果这2个点分别在S1和S2中,问题就不那么简单了。下面的基本算法中,将对其作具体分析。 二、基本算法 假设用x轴上某个点m将S划分为2个集合S1和S2,使得S1={x∈S|x<=m};S2={x ∈S|x>m}。因此,对于所有p∈S1和q∈S2有p

用分治法求解棋盘覆盖问题

棋盘覆盖问题 问题描述: 在一个2k ×2k (k ≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中出现的位置有4k 中情形,因而有4k 中不同的棋盘,图(a )所示是k=2时16种棋盘中的一个。棋盘覆盖问题要求用图(b )所示的4中不同形状的L 型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且热河亮哥L 型骨牌不得重复覆盖。 问题分析: K>0时,可将2k ×2k 的棋盘划分为4个2k-1×2k-1的子棋盘。这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有1个子棋盘中有特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化成为特殊棋盘,以便采用递归方法求解,可以用一个L 型骨牌覆盖这3个较小的棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。 问题求解: 下面介绍棋盘覆盖问题中数据结构的设计。 (1) 棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中size=2k 。为了 在递归处理的过程中使用同一个棋盘,将数组board 设为全局变量。 (2) 子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上 角的下标tr 、tc 和棋盘大小s 表示。 (3) 特殊方格:用board[dr][dc]表示特殊方格,dr 和dc 是该特殊方格在二维数组 board 中的下标。 (4) L 型骨牌:一个2k ×2k 的棋盘中有一个特殊方格,所以,用到L 型骨牌的个数 为(4k -1)/3,将所有L 型骨牌从1开始连续编号,用一个全局变量tile 表示。 图(b ) 图 (a )

实验七 最近点对问题的设计与实现

实验七最近点对问题的设计与实现 一、实验目的 1.掌握分治算法的基本原理 2.利用分治策略编程解决最近点对问题 二、实验要求 1.设计算法 2.写出相应程序 3.保存和打印出程序的运行结果,并结合程序进行分析。 三、实验内容 算法思想:用分治法解决最近对问题,很自然的想法就是将集合S分成两个子集S1和S2,每个子集中有n/2个点。然后在每个子集中递归地求其最接近的点对,在求出每个子集的最接近点对后,在合并步中,如果集合S 中最接近的两个点都在子集S1或S2中,则问题很容易解决,如果这两个点分别在S1和S2中,则根据具体情况具体分析。 1、考虑一维情形下的最近点对问题: 设x1, x2, …, xn是x轴上有n个点构成的集合S,最近对问题就是找出集合S中距离最近的点对。 算法思想:用x轴上的某个点m将S划分为两个集合S1和S2,并且S1和S2含有点的个数近似相同。递归地在S1和S2上求出最接近点对 (p1, p2) 和(q1, q2),如果集合S 中的最接近点对都在子集S1或S2中,则d=min{(p1, p2), (q1, q2)}即为所求,如果集合S中的最接近点对分别在S1和S2中,则一定是(p3, q3),其中,p3是子集S1中的最大值,q3是子集S2中的最小值。 例如:(1)输入 -8,-5,-4,1,3,7,输出为1. (2)输入 -8,-5,-2,1,3,7,输出为2. (3)输入 -8,-4,-1,1,4,7,输出为2.

附加题:(有时间可继续完成下面内容) 2、考虑一维情形下的最近点对问题: 设p1=(x1, y1), p2=(x2, y2), …, p n=(x n, y n)是平面上n个点构成的集合S,最近对问题就是找出集合S中距离最近的点对。 算法:

蛮力法分治法求最近对

实验题目 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 实验目的 (1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。 实验内容(包括代码和对应的执行结果截图) #include #include #include 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.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

分治法实现快速排序

实验一 实验名称:利用分治法实现快速排序实验时间: 2012年12月成绩:一、实验目的 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。 本实验的目的是利用分治策略实现快速排序算法。 二、实验内容 快速排序算法是基于分治策略的排序算法。其基本思想是,对于输入的子数组a[p:r],按以下三个步骤进行排序。 (1)分解:以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1:r],使a[p:q-1]中任何一个元素小于等于a[q],而a[q+1:r]中任何一个元素大于等于a[q]。下标q在划分过程中确定。 (2)递归求解:通过递归调用快速排序算法分别对a[p:q-1]和a[q+1:r]进行排序。 (3)合并:由于对a[p:q-1]和a[q+1:r]的排序是就地进行的,所以在a[p:q-1]和a[q+1:r]都已排好的序后,不需要执行任何计算,a[p:r]就已排好序。基于这个思想,可实现的快速排序算法如下:void QuickSort(int a[],int p,int r)

{ if(px); if(i>=j) break;

最近点对问题

算法分析与设计最近对问题

最近对问题 问题描述: 在二维平面上的n 个点中,如何快速的找出最近的一对点,就是最近点对问题。 程序设计思想: 1.蛮力法求最近对问题: 基本思想: 分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计 算两次距离,只考虑j i <的那些点对() j i P P ,。 复杂度分析: 对于此算法,主要就是算两个点的欧几里得距离。注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。所以复杂度就是求平方,求执行次数为: )()1()(2n O n n n T =-=;即时间复杂度为)(2n O 。 2.分治法求最近对问题: 基本思想: 用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。则基本过程为:找一条中垂线m (坐位S 集合x 坐标的中位数)把n 个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d 的点,更新最短距离,直到循环结束,即可求出最短距离。 复杂度分析: 应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。 由以上分析:合并子问题的解的时间)1()(O n f =。进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =。 程序代码: #include #include #include #define NUM 1000 typedef struct{ int x;

分治法实验报告

算法实验报告一分治法实验 一、实验目的及要求 利用分治方法设计大整数乘法的递归算法,掌握分治法的基本思想和算法设计的基本步 骤。 要求:设计十进制的大整数乘法,必须利用分治的思想编写算法,利用c语言(或者c++ 语言)实现算法,给出程序的正确运行结果。(必须完成) 设计二进制的大整数乘法,要求利用分治的思想编写递归算法,并可以实现多位数的乘 法(利用数组实现),给出程序的正确运行结果。(任选) 二、算法描述 1、 输入两个相同位数的大整数u,v 输出uv的值 判断大整数的位数i; w=u/10^(i/2); y=v/10^(i/2); x=u-w*10^(i/2); z= v-y*10^(i/2); 然后将w,x,y,z代入公式求得最后结果 uv=wy10^i+((w+x)(y+z)-wy-xz)10^(i/2)+xz 三、调试过程及运行结果 在实验中我遇到的问题: 原来以为这两个大整数的位数不同,结果题目要求是相同位数的大整数在写10的多少 次方时,写的是10^(i/2),10^(i),结果不对,我就将它改成了for循环语句 四、实验总结 在本次实验中,我知道了分治算法,以及分治算法的基本思想。我还掌握了编写大整数 乘法的算法与步骤,以及如何修改在编写程序时遇到的问题。 五、附录(源程序代码清单) 1、#include<iostream.h> int weishu(int x) { int i; while(x!=0) { x=x/10; i++; } return i; } void main() { int u,v; cout<<输入两个位数相同的大整数:<<endl; cin>>u; cin>>v;

用蛮力法和分治法解决最近对问题

算法分析与复杂型设计作业 学院计算机与控制工程学院 专业计算机软件与理论 班级 Y130701 学生姓名郑晓璐 流水号 20130789 2014年4月

问题: 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 蛮力算法描述: int ClosestPoints(int n, int x[ ], int y[ ]){ minDist=Double.POSITIVE_INFINITY;; for (i=1; i< n; i++) for (j=i+1; j<=n; j++) { d=(x[i]-x[j])* (x[i]-x[j])+(y[i]-y[j])* (y[i]-y[j]); if (d< minDist) { minDist=d; index1=i; index2=j; } } return minDist; } 程序: import java.util.*; public class ClosestPair1{ public static void main(String[] args) { /** *输入需要比较的点的对数存在变量n中 */ Scanner in=new Scanner(System.in); System.out.println("How many pairs of points to compare?(有多少对点需要比较?)"); int n=in.nextInt(); int[] x=new int[n]; int[] y=new int[n]; /** *输入这些点的横坐标和纵坐标分别存储在x[n]和y[n] */ System.out.println("Please enter these points,X-coordinate(请输入这些点,横坐标):"); for(int i=0;i< n;i++) { x[i]=in.nextInt(); }

最近点对问题 二维-实验报告

实验一 课程名称:算法设计与实现实验名称:分治策略-一维点对问题 实验日期:2019年3月20日仪器编号:007 班级:数媒0000班姓名:郝仁学号0000000000 实验内容 请采用分治策略实现二维情形下的最近点对问题求解。 (1)二维平面上 n 个点集 X,Y 坐标的的排序请使用快递排序算法。 实验分析 如果将点的距离两两计算出来需要O(n2)O(n2)的时间复杂度,显然不是最优方案。先考虑一维数组情况,如果数组已经排好序,则只需要再遍历一遍,找到相邻值的最小距离即可,时间复杂度只是O(nlog(n))O(nlog(n)),但是这种方法不能推广到二维情况。因为按照一个维度排序后,相邻点的最小距离并不是所有距离中的最小值。 这里可以采用分治法进行改进,首先将点集按照横坐标排序,根据其中心点将点集一分为二,构成最小距离的两个点要么同时在左边的子点集,要么同时在右边的子点集,或者一个在左边一个在右边。前两种情况可以递归解决,这里主要考察第三种情况。 实验源代码 // 二维点对ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include"pch.h" #include #include #include using namespace std; const int M = 999; //用类PointX和PointY表示依x坐标和y坐标排好序的点 class PointX { public: int operator<=(PointX a)const {

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

深圳大学实验报告

教务部制

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

实验过程及内容: (实验代码已作为附件提交,名为“算法实验二.cpp) 当点的数量小丁3时,直接计算,当点的个数大丁3时,采用分治法当N=1时 当N=2时 只有两个点,最近点对就是这两个点 测试数据为(1,1 ) (2,2) 预期结果为d=1.414

利用分治法求解空中飞行管理问题

收稿日期:2006-04-15 作者简介:应惠芬(1970-),女,浙江仙居人,高级讲师,硕士1 浙江交通职业技术学院学报,第7卷第4期,2006年12月 Journal of Zhejiang T ransportation C ollege V ol 17N o 14,Dec 12006 利用分治法求解空中飞行管理问题 应惠芬1,王桂云2 (11杭州万向职业技术学院,浙江杭州 310023;21浙江交通职业技术学院,浙江杭州 311112) 摘 要:分治法是一种常用的问题求解方法,可以简化问题规模,降低计算复杂度。飞行管理问题实质上属于搜索问题,利用常规方法解决时间耗费大,而利用分治法可以得到很好的解决。 关键词:分治法;计算复杂度;数学模型中图分类号:TP30116;V355 文献标识码:A 文章编号:1671-234X (2006)04-0046-04 0 引 言 随着空中各种飞机数量的增加,飞行安全控制变得尤为重要,要想提高空中飞行的安全系数,其中一个亟需解决的问题就是预先知道空中哪两架飞机之间具有最大碰撞危险。如果知道了这两架具有最大碰撞危险的飞机,我们就预先通知飞行员进行相应的安全飞行,以避免碰撞。从穷举法的角度很容易解决这个问题,但是效率太低,时间复杂度是O (n 2),不符合实际需要,利用分治法分而制之的思想,降低问题复杂度,通过建模求解,把时间复杂度降到O (nlogn ),可以较好地解决实际问题。 1 分治法 分治法基本思想[2]:任何一个用计算机求解的问题时间复杂度都与其规模N 有关。问题的规模越小,越容易直接求解,时间复杂度越少。而当问题规模较大时,时间复杂度会大幅度增加。分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。 分治法在每层递归上都有三个步骤: (1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形成相同的子问题; (2)解决:若子问题规模较小而容易被解决则直接解决,否则递归地解各个子问题; (3)合并:将各个子问题的解合并为原问题的解。 2 问题描述 为了便于分析和解决问题,以二维空间为例,用质点代替二维坐标系X -O -Y 中分布n 的架飞机,其坐标分别为:(x 1,y 1),(x 2,y 2)…(x n ,y n ),问题目标是寻找这n 个点中距离最近的两个点坐标及其距离。 3 问题分析及模型建立 利用穷举法求解最简单,求出所有点之间的距 离,再从中找到最小值,但是效率低,不值得推荐。311 一维点集的情况 利用分治法,把集合S 分成两个子集S 1和

算法论文_分治法和分支限界

成绩评定表

课程设计任务书

计算效率是一个古老的研究课题。科学技术的发展使得计算日趋复杂,计算量越来越大,许多理论上可计算的问题,常常由于其计算量巨大布变成了现实不可计算的问题,这就产生了理论可计算而现实不可计算的矛盾,而算法设计与分析的任务就是对各类具体的问题设计高质量的算法,以及研究设计算法的一般规律和方法。常用的算法设计方法主要有分治法、动态规划、贪婪法和回溯法等。 问题一:运用分治法对多点最近距离问题进行算法设计,把问题分解为不是相互独立的子问题,计算保存子问题的答案,从而再求重复子问题时可以直接找到答案。通过反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。 问题二:运用分支限界对旅行商售货员问题进行算法设计,求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。)分支限界法首先确定一个合理的限界函数,并根据限界函数确定目标函数的界;然后按照广度优先策略遍历问题的解空间树,在某一分支上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值(对最小化问题,估算结点的下界,对最大化问题,估算结点的上界)。如果某孩子结点的目标函数值超出目标函数的界,则将其丢弃(从此结点生成的解不会比目前已得的更好),否则入待处理。 关键词:算法设计与分析;分支限界法;分治法

1分治法解决最近距离问题 (1) 1.1 问题描述 (1) 1.2 算法设计 (2) 1.3 算法实现 (3) 1.4 运行结果与分析 (6) 2分支限界解决旅行商售货员问题 (7) 2.1 问题描述 (7) 2.2 算法设计 (8) 2.3 算法实现 (9) 2.4 运行结果与分析 (14) 总结 (15) 参考文献 (16)

分治法 题目

Problem2查找第k大元素 题目描述 有N个数,请找出其中第k大的数(N<=10000) 输入 输入第一行为N、K,第二行有N个数 输出 输出第K大的数 Problem3麦森数 题目描述 形如2^P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P 是个素数,2^P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。 任务:从文件中输入P(1000a[j]那么我们称a[i]与a[j]是一对逆序对,现要求求出数列{an}中逆序对的个数 输入

输入第一行为整数N(N<=10000),第二行有N个数,即为数列{an} 输出 输出仅一个数,即逆序对的个数 Problem5寻找最近点对 题目描述 给出平面内的N(N<=10000)个点,点两两都有一个距离,现要求出所有点对中距离最小的那一对 输入 输入第一行为N,后面有N行,每行两个数分别描述每个点的横纵坐标 输出 输出一个数,即最近点对的距离 Problem6剔除多余括号 题目描述 键盘输入一个含有括号的四则运算表达式,可能含有多余的括号,编程整理该表达式,去掉所有多余的括号,原表达式中所有变量和运算符相对位置保持不变,并保持与原表达式等价。 输入 输入一行,即为表达式,长度小于250 输出 输出也一行,为剔出多余括号之后的表达式 Problem7赛程安排 题目描述 有n个编号为1到n 的运动员参加某项运动的单循环比赛,即每个运动员要和所有其他运动员进行一次比赛。试为这n个运动员安排一个比赛日程,使得每个运动员每天只进行

相关文档
最新文档