最大子段和代码

最大子段和代码
最大子段和代码

#include

#include

#include

#include

#define MAX 500

using namespace std;

int MaxSum(int a[],int n,int *s,int *t);

int main()

{

FILE *fp;

if((fp=fopen("附件 2.最大子段和输入数据-序列 1.txt","r"))==NULL) {puts("FILE ERROR!");return 0;}

else

{

int a[MAX];

for(int j=0;j

int i=0;

while(!feof(fp)) {fscanf(fp,"%d",&a[i++]);}

int s=0,t=0;

printf("最大子段和%d\n",MaxSum(a,i-1,&s,&t));

printf("位置:%d----%d\n",s,t);

}

if((fp=fopen("附件 2.最大子段和输入数据-序列 2.txt","r"))==NULL) {puts("FILE ERROR!");return 0;}

else

{

int a[MAX];

for(int j=0;j

int i=0;

while(!feof(fp)) {fscanf(fp,"%d",&a[i++]);}

int s=0,t=0;

printf("最大子段和%d\n",MaxSum(a,i-1,&s,&t));

printf("位置:%d----%d",s,t);

}

}

int MaxSum(int a[],int n,int *s,int *t)

{

int sum=0,b=0;

int i;

for (i=0;i

{

if(b>0)

{b+=a[i];}

else

{b=a[i];*s=i+1;}

if(b>sum)

{sum=b;*t=i+1;} }

return sum;

}

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

算法分析与设计 实验三 最大子段和问题

昆明理工大学信息工程与自动化学院学生实验报告 ( 201 — 201 学年 第 1 学期 ) 课程名称:算法分析与设计 开课实验室: 年 月 日 一、上机目的及内容 1.上机内容 给定有n 个整数(可能有负整数)组成的序列(a 1,a 2,…,a n ),求改序列形如 ∑=j k k a 1 的子段和的 最大值,当所有整数均为负整数时,其最大子段和为0。 2.上机目的 (1)复习数据结构课程的相关知识,实现课程间的平滑过渡; (2)掌握并应用算法的数学分析和后验分析方法; (3)理解这样一个观点:不同的算法能够解决相同的问题,这些算法的解题思路不同,复杂程度不同,解题效率也不同。 二、实验原理及基本技术路线图(方框原理图或程序流程图) (1)分别用穷举法、分治法和动态规划法设计最大子段和问题的算法; (2)对所设计的算法采用大O 符号进行时间复杂性分析; (3)上机实现算法,并用计数法和计时法分别测算算法的运行时间; (4)通过分析对比,得出自己的结论。 穷举法是用一个二维数组将从i 到j 的和都记录下来,再比较各元素的大小,时间复杂性为O (n 2),分治法的设计思想是不断将问题为子问题,然后求解子问题,最后对解进行合并,时间复杂性为O(nlog n ),动态规划法的设计思想是将问题划分为若干个子问题,时间复杂度为O(n)。

分治法流程图:

穷举法流程图: 动态规划法流程图: 三、所用仪器、材料(设备名称、型号、规格等或使用软件) 1台PC 及VISUAL C++6.0软件

四、实验方法、步骤(或:程序代码或操作过程) 程序代码: //穷举法 #include void main() { int i,j,n; int num[100],a[100],max; printf("\t\t\t 最大子段和问题(穷举法)\n\n"); printf("请输入所要求最大字段和整数的个数:\n"); scanf("%d",&n); printf("请分别输入这%d个整数的值:\n",n); for(i=0;i int MaxSum(int a[],int left,int right) { int sum=0; if (left==right) {

算法练习题-分章节-带答案

算法练习题-分章节-带答案

算法练习题---算法概述 一、选择题 1、下面关于算法的描述,正确的是() A、一个算法只能有一个输入 B、算法只能用框图来表示 C、一个算法的执行步骤可以是无限的 D、一个完整的算法,不管用什么方法来表示,都至少有一个输出结果 2、一位爱好程序设计的同学,想通过程序设计解决“韩信点兵”的问题,他制定的如下工作过程中,更恰当的是() A、设计算法,编写程序,提出问题,运行程序,得到答案 B、分析问题,编写程序,设计算法,运行程序,得到答案 C、分析问题,设计算法,编写程序,运行程序,得到答案 D、设计算法,提出问题,编写程序,运行程序,得到答案 3、下面说法正确的是() A、算法+数据结构=程序 B、算法就是程序 C、数据结构就是程序 D、算法包括数据结构 4、衡量一个算法好坏的标准是()。 A、运行速度快 B、占用空间少 C、时间复杂度低 D、代码短 5、解决一个问题通常有多种方法。若说一个算法“有效”是指( )。 A、这个算法能在一定的时间和空间资源限制内将问题解决 B、这个算法能在人的反应时间内将问题解决 C、这个算法比其他已知算法都更快地将问题解决 D、A和C 6、算法分析中,记号O表示(),记号Ω表示()。 A.渐进下界 B.渐进上界 C.非紧上界 D.非紧下界 7、以下关于渐进记号的性质是正确的有:() A.f(n)(g(n)),g(n)(h(n))f(n)(h(n)) =Θ=Θ?=Θ B.f(n)O(g(n)),g(n)O(h(n))h(n)O(f(n)) ==?= C. O(f(n))+O(g(n)) = O(min{f(n),g(n)}) D.f(n)O(g(n))g(n)O(f(n)) =?=

最大子段和动态规划法

实验名称: 最大子段和问题 实验目的: 了解最大子段和问题 实验环境: 操作系统:Windows XP Professional SP3 机器配置:Intel Pentium4 CPU 3.0GHz , 512MB 内存 开发工具:eclipse 实验内容: 1. 求数列的最大子段和(要求时间复杂为nlogn) (算法设计与分析 吕国英 清华大学出 版社 135页 4..3.3 二分法变异) (分治法) (也可用动态规划算法 参看递归王晓东计算机算法设计与分析第三版p61页) 算法的设计思想: 在对分治法德算法分析中注意到,若记???? ? ? <=<==∑=j i k k a n j i i b ][max ][,1<=j<=n,则所求的 最大子段和为: ][1max ][1max 1max ][1max j b n j k a j i n j k a n j i j i k j i k <=<== <=<=<=<==????? ?<=<=<=∑ ∑== 分为两种情况: (1)、当b[j-1]>0时,b[j]=b[j-1]+a[j]。 (2)、当b[j-1]<0时,b[j]=a[j]。 由此可得计算b[j]的动态规划递归式为: b[j]=max }{][],[]1[j a j a j b +-,1<=j<=n 由分析可知:次算法一共比较了n 次,故: T(n)=O(n)

据此可以写出如下程序: 实验步骤: 程序代码如下: package s; public class Po{ public static void main(String[] args) { int[] a=new int[10]; int[] b=new int[10]; int[] x=new int[10]; int start=0; int end = 0; System.out.print("数组为:");//随机赋值 for(int i =0;i<10;i++){ a[i]=(int)(Math.random()*100-50); System.out.print(a[i]+" "); } System.out.print("\n"); tem(a,x,b); int max=maxSum(a,b,end); System.out.print("最大子段和为:"); System.out.println(max); System.out.print("结束位置为:"); System.out.println(findend(a,b,end)); int begin=findStart(a,b,start,end); System.out.print("开始位置为:"); System.out.println(begin); systemout(x,start,end,a,b); } public static void tem(int a[],int x[],int b[]) {int n=a.length-1; int sum=0; b[0]=x[0];

分治法求最大子段和问题

分治法求最大子段和问题 共有四种方法: 算法一; 算法二; 算法三、Divide and Conquer 算法四源代码、On-line Algorithm 算法一源代码: /*Given (possibly negative) integers A1, A2, …, AN, find the maximum value. 找最大子段和*/ #include #include #include intMaxSubsequenceSum(int A[],int N); main() { inti,N,*A,MaxSum,judge; LARGE_INTEGER begin,end,frequency; //代表64位有符号整数,记录程序运行时间QueryPerformanceFrequency(&frequency);//可以获得当前的处理器的频率 printf("输入整数的个数:"); scanf("%d",&N); A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间 printf("自行输入数据请按1,随机产生数据请按2\n"); scanf("%d",&judge); if(judge==1){ //自行输入数据 printf("输入%d个整数:",N); for(i=0;i

分治法实验报告一

宁波工程学院电信学院计算机系 实验报告 课程名称:算法设计与分析实验项目:用分治法算法解 最接近点对问题 指导教师:崔迪 实验位置:软件工程实验室姓名: 班级: 学号: 日期: 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/a3476950.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 {

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

一、算法分析 该算法的问题描述为:给定二维平面上的点集,求解距离最近的两个点,并计算出两点间的距离。 解决问题最初的思路为穷举法。对所有两点间的组合计算其距离。然后对其进行比较,找出最小值即可。不过这样做的缺点是时间复杂度和空间复杂度十分庞大,消耗巨量资源。如有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的数列{An}中,求i,j(1<=i<=j<=n),使得数列{An}中,第i个元素到第j个元素之间,所有元素的和最大。例如:-2, 11, -4, 13, -5, -2时答案为20(11 -4 13) 解法一穷举法:以前我想出了一种算法,具体做法是:取出所给序列的所有子序列求和,共分n组,第一组长度为1,有n个;第二组长度为2, 有n-1个;……,最后一组,长度为n,只有一个。比较这n(n+1)/2个序列的和,再将每组的最大值比较,从而得到最大值以及其上下标。 a1 a2 a n-1 a n a1+a2 a2+a3 a n-1+a n a1+a2+a3 a2+a3+a4 ...... ...... ...... a1+a2......+a n-1 a2+a3......+a n a1+a2......+a n-1 +a n 此算法比较直接,也容易写出代码,但其时间开销为O(n2),空间开销为O(n),效率不高。 解法二:动态规划求解, 1 2 F[i]:表示以元素i结尾的连续最大子序列的和 那么对于第i个元素来说,要形成连续的最大子序列,只和相邻的前一个元素有关。因为可以不取,所以如果元素a[i]连接到以元素i-1结尾的最大连续子序列f[i-1]后是负数(f[i-1]+a[i]<0);则宁可不取,这样最大连续子序列和为0。 动态方程: f[i]:=max{0,f[I-1]+a[i]} (边界条件:f[0]=0;) 3、代码1: for I:=1 to n do if (f[I-1]+a[i])>0 then f[i]:=f[I-1]+a[i] else f[i]:=0; max:=-maxlongint; for i:=1 to n do if f[i]>max then max:=f[i];

最近点对分治法

假设在一片金属上钻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/a3476950.html,/p-198711591.html?qq-pf-to=pcqq.c2c 代码如下: #include #include #include

算法分析习题详细答案五

1.最大子段和问题:给定整数序列 n a a a ,,,21 ,求该序列形如 j i k k a 的子段和 的最大值: j i k k n j i a 1max ,0max 1) 已知一个简单算法如下: int Maxsum(int n,int a,int& best i,int& bestj){ int sum = 0; for (int i=1;i<=n;i++){ int suma = 0; for (int j=i;j<=n;j++){ suma + = a[j]; if (suma > sum){ sum = suma; besti = i; bestj = j; } } } return sum; }试分析该算法的时间复杂性。 2) 试用分治算法解最大子段和问题,并分析算法的时间复杂性。 3) 试说明最大子段和问题具有最优子结构性质,并设计一个动态规划算法解最大子段和问题。分析算法的时间复杂度。 (提示:令1()max ,1,2,,j k i j n k i b j a j n L ) 解:1)分析按照第一章,列出步数统计表,计算可得)(2 n O 2)分治算法:将所给的序列a[1:n]分为两段a [1:n/2]、a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种可能: ①a[1:n]的最大子段和与a[1:n/2]的最大子段和相同; ②a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同; ③a[1:n]的最大子段和为两部分的字段和组成,即 j n j i l n i j a a a a a 122;

intMaxSubSum ( int *a, int left , int right){ int sum =0; if( left==right) sum = a[left] > 0? a[ left]:0 ; else {int center = ( left + right) /2; int leftsum =MaxSubSum ( a, left , center) ; int rightsum =MaxSubSum ( a, center +1, right) ; int s_1 =0; int left_sum =0; for ( int i = center ; i >= left; i--){ left_sum + = a [ i ]; if( left_sum > s1) s1 = left_sum; } int s2 =0; int right_sum =0; for ( int i = center +1; i <= right ; i++){ right_sum + = a[ i]; if( right_sum > s2) s2 = right_sum; } sum = s1 + s2; if ( sum < leftsum) sum = leftsum; if ( sum < rightsum) sum = rightsum; } return sum; } int MaxSum2 (int n){ int a; returnMaxSubSum ( a, 1, n) ; } 该算法所需的计算时间T(n)满足典型的分治算法递归分式T(n)=2T(n/2)+O(n),分治算法的时间复杂度为O(nlogn)

最近点对问题

最近点对问题 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

最大字段和问题

最大字段和问题 1.实验题目 给定由N 个整数(可能有负整数)组成的序列(1a ,2a ,…,n a ),求该序列形如∑=j i k k a 的子段和的最大值,当所有整数均为负整数是,其最大子段和为0。 2.实验目的 (1)深刻掌握动态规划法的设计思想并能熟练运用; (2)理解这样一个观点:同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修正的结果。 3.实验分析 蛮力法:利用3个for 的嵌套(实现从第1个数开始计算子段长度为1,2,3…n 的子 段和,同理计算出第2个数开始的长度为1,2,3…n-1的子段和,依次类推到第n 个数开始计算的长为1的子段和)和一个if (用来比较大小),将其所有子段的和计算出来并将最大子段和赋值给summax1。 用了3个for 嵌套所以时间复杂性为○(n 3)。 分治法: (1)划分:按照平衡子问题的原则,将序列(1a ,2a ,…,n a )划分成长度相同的 两个字序列(1a ,…,??2/n a )和(??12/+n a ,…,n a ) 。 (2)求解子问题:对于划分阶段的情况分别的两段可用递归求解,如果最大子段和在 两端之间需要分别计算 s1=?? ??)2/1(max 2/n i a n i k k ≤≤∑=,s2=????)2/(max 12/n j n a j n k k ≤≤∑+=, 则s1+s2为最大子段和。若然只在左边或右边,那就好办了,前者视s1为summax2,后者视s2 o summax2。 (3)合并:比较在划分阶段的3种情况下的最大子段和,取三者之中的较大者为原问 题的解。 (4)时间复杂性分析: f(n) = 2*f(n/2) + ○(n/2), 最后为○(nlogn)。 动态规划法: 动态规划法求解最大字段和问题的关键是要确定动态规划函数。记 )1(max )(1n j a j b i i k k j i ≤≤? ?????=∑=≤≤ 则

最大字段和

最大字段和 【实验目的】 1掌握动态规划法的设计思想并能熟练运用; 2分别用分治法和动态规划法设计最大子段和问题的算法; 【实验设备与环境】 1 PC机一台 2 Turbo C 或VC++ 【实验内容:】 给定由n个整数(可能为负整数)组成的序列a1, a2, …, an,求该序列形如的子段和的最大值,当所有整数均为负整数时定义其最大子段和为0。 【实验方法步骤】 1用分治法求最大子段和 程序代码: #include int MaxSum(int a[],int left,int right) { int i,sum=0; if(left==right) sum=a[left]>0?a[left]:0; else { int center=(left+right)/2; int leftsum=MaxSum(a,left,center); int rightsum=MaxSum(a,center+1,right); int s1=0,s2=0,lefts=0,rights=0; for(i=center;i>=left;i--) { lefts+=a[i]; if(lefts>s1) s1=lefts; }

for(i=center+1;i<=right;i++) { rights+=a[i]; if(rights>s2) s2=rights; } sum=s1+s2; if(sum

算法(复习题)1

平均情况:设待查找的元素在数组中的概率为P,不在数组中的概率为1-P,若出现在数组中每个位置的概率是均等的为p/n T(n)=P1D1+P2D2+...+PiDi+(1-P)Dn+1 =p/2+n(1-p/2) 1.叙述分治算法和动态规划算法的基本思想,并比较两种算法的异同。答:分治法将待求解的问题划分成K个较小规模的子问题,对这K个子问题分别求解,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解. 动态规划将待求解的问题分解成若干的子问题,自底向上地通过求解子问题的解得到原问题的解。动态规划将每个子问题只求解一次并将其解保存在一个表格中,当需要再次求解此子问题时,只是简单的通过查表过的该子问题的解,避免了大量的重复计算. 异同:分治法求解的问题分解后的子问题都是独立的,而使用动态规划求解的问题分解后得到的子问题往往不是相互独立的。 分治法是自顶向下用递归的方法解决问题,而动态规划则是自底向上非递归解决问题。 1.简述分治算法求解过程的三个阶段。 答:(1)划分:既然是分治,当然需要把规模为n的原问题划分为k个规模较小的子问题,并尽量使这k个子问题的规模大致相同。 (2)求解子问题:各子问题的解法与原问题的解法通常是相同的,可以用递归的方法求解各个子问题,有时递归处理也可以用循环来实现。 (3)合并:把各个子问题的解合并起来,合并的代价因情况不同有很大差异,分治算法的有效性很大程度上依赖于合并的实现。 2.叙述分治法的基本思想,并分析分治法与减治法二者的区别。 答:分治法将待求解的问题划分成K个较小规模的子问题,对这K个子问题分别求解,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解. 区别:分治法是把一个大问题划分成若干个子问题,分别求解各个子问题,然后把子问题的解进行合并并得到原问题的解。减治法同样是把一个大问题划分成若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。 3.设计分治算法求一个数组中最大元素的位置,建立该算法时间复杂性的 递推式并给出其复杂性的大O表示。 答:设数组a1,a2...an int maxpos(a[],i,j); {if(i==j) return i; mid=(i+j)/2; lmaxpos=maxpos(a,i,mid); rmaxpos=maxpos(a,mid+1,j); if(a[lmaxpos]>=a[rmoxpos]) return lmaxpos; else return rmaxpos;} T(1)=O(n) n=1; T(n)=2T(n/2)+O(1) n>1;

算法分析考试题

1. )(n T 给定数组a[0:n-1],试设计一个算法,在最坏情况下用n+[logn]-2次比较找出 a[0:n-1] 中的元素的最大值和次大值. (算法分析与设计习题 2.16 ) (分治法) a 、 算法思想 用分治法求最大值和次大值首先将问题划分,即将划分成长度相等的两个序列,递归求出左边的最大值次大值,再求出右边的的最大值次大值,比较左右两边,最后得出问题的解。 b 、复杂度分析: 把问题划分为左右两种的情况,需要分别递归求解,时间复杂度可如下计算: 有递推公式为: T(n)=1 n=1 T(n)= 2T(n/2)+1 n>1 所以,分治算法的时间复杂度是n+[logn]-2,当n 为奇数时,logn 取上线,当n 为偶数时,logn 取下线。//不知道为什么会-2! C 、代码实现: #include int a[100]; void maxcmax(int i,int j,int &max,int &cmax) { int lmax,lcmax,rmax,rcmax; int mid; if (i==j) { max=a[i]; cmax=a[i]; } else if (i==j-1) if (a[i]rmax)

if(lcmax>rmax) { max=lmax; cmax=lcmax; } else { max=lmax; cmax=rmax; } else if(rcmax>lmax) { if(rmax==rcmax) { max=rmax; cmax=lmax; } else { max=rmax; cmax=rcmax; } } else { max=rmax; cmax=lmax; } } } int main() { int n; int max,cmax; printf("输入数组长度"); scanf("%d",&n); printf("输入数组:\n"); for(int i=0;i

最大子段和三种求解方法

1、最大子段和问题的简单算法: 代码: #include using namespace std; int MaxSum(int a[],int n,int &besti,int &bestj){ int sum=0; int i,j,k; for(i=1;i<=n;i++) for(j=i;j<=n;j++) { int thissum=0; for(k=i;k<=j;k++)thissum+=a[k]; if(thissum>sum){ sum=thissum; besti=i; bestj=j; } } return sum; } int main(){ int n,a[100],m,i,j,maxsum; cout<<"请输入整数序列的元素个数n:"<>n; cout<<"请输入序列中各元素的值a[i](一共"<>a[m]; for(m=0;m>a[m]; int b[100];

for(m=0;m using namespace std; int MaxSum(int a[],int n,int &besti,int &bestj){ int sum=0; int i,j,k; for(i=1;i<=n;i++){ int thissum=0; for(j=i;j<=n;j++) { thissum+=a[j]; if(thissum>sum){ sum=thissum; besti=i; bestj=j; } } } return sum; }

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

实验七最近点对问题的设计与实现 一、实验目的 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中距离最近的点对。 算法:

最大子段和问题实验报告

实验四最大子段和问题 1.实验目的 (1)掌握动态规划的设计思想并能熟练运用; (2)理解这样一个观点:同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修正的结果; 2.实验要求 (1)分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法; (2)比较不同算法的时间性能; (3)给出测试数据,写出程序文档; 3.实验设备和软件环境 操作系统:Windows 7(64x) 开发工具:Visual Studio 2013 4.实验步骤 以下实验数据都是以数组a[]={-2, 11, -4, 13, -5, -2}为例子; 蛮力法 蛮力法是首先通过两个for循环去求出所有子段的值,然后通过if语句查找出maxsum,返回子序列的最大子段和; 分治法 (1)划分:按照平衡子问题的原则,将序列(a1,a2,…,an)划分成长度相同的两个子序列(a1,a2,...,an/2)和(an/2+1,…,an); (2)求解子问题:对与划分阶段的情况①和②可递归求解,情况③需要分别计算

s1=max{}(1<=i<=n/2),s2=max{}(n/2+1<=j<=n),则s1+s2为情况③的最大子段和。 (3)合并:比较在划分阶段三种情况下的最大子段和,取三者中比较大者为原问题的解。动态规划法划分子问题 (1)划分子问题; (2)确定动态规划函数; (3)填写表格; 分为两种情况: (1)、当b[j-1]>0时,b[j]=b[j-1]+a[j]。 (2)、当b[j-1]<0时,b[j]=a[j] 然后做递归操作求出最大子段和; 5.实验结果 蛮力法 #include #include<> using namespace std; /*------------------------------------------------------------------------------*/ int manlifa(int a[],int x) { int i, j,sum=0,maxsum=0; for (i = 0; i < x; i++) { for (j = i+1; j < x; j++) { sum = a[i]; a[i] += a[j]; if (a[i]>sum) { sum = a[i]; } if (sum>maxsum) { maxsum = sum;

相关文档
最新文档