当前位置:文档之家› 算法分析习题详细答案五

算法分析习题详细答案五

1.最大子段和问题:给定整数序列 n a a a ,,,21 ,求该序列形如 jik k a 的子段和的最大值:ji k k n j i a 1max ,0max1) 已知一个简单算法如下: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,,jki j nk ib j a j n L )解:1)分析按照第一章,列出步数统计表,计算可得)(2n O2)分治算法:将所给的序列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 jil n i ja a a a a122;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)3)设}{max )(1 j ik k ji a j b ,则最大子段和为).(max max max max max 11111j b a a nj jik k ji n j j ik k nj n i},,,,max {)(11211j j j j j j j a a a a a a a a a j b最大子段和实际就是)}(,),2(),1(max{n b b b .要说明最大子段和具有最优子结构性质,只要找到其前后步骤的迭代关系即可。

},)1(max {},}{max max {},}{max {}{max )(1111111j j j j j ik k j i j j i j j i k k ji k k j i a a j b a a a a a a a j b若0)1( j b , j a j b j b )1()(;若0)1( j b ,j a j b )(。

因此,计算)(j b 的动态规划的公式为:.1},,)1(max {)(n j a a j b j b j jintMaxSum (int* a ,int n ) {int sum = 0, b = 0,j=0; for( int i=1;i<=n;i++) { if( b >0)b = b + a [i];elseb = a [i];end{if} if( b > sum)sum = b;j=i ; end{if}}return sum; }自行推导,答案:时间复杂度为O (n )。

2.动态规划算法的时间复杂度为O (n )(双机调度问题)用两台处理机A 和B 处理n 个作业。

设第i 个作业交给机器A 处理时所需要的时间是i a ,若由机器B 来处理,则所需要的时间是i b 。

现在要求每个作业只能由一台机器处理,每台机器都不能同时处理两个作业。

设计一个动态规划算法,使得这两台机器处理完这n 个作业的时间最短(从任何一台机器开工到最后一台机器停工的总的时间)。

以下面的例子说明你的算法:)4,3,11,4,8,3(),,,,,(),2,5,10,7,5,2(),,,,,(,6654321654321 b b b b b b a a a a a a n解:(思路一)删除(思路二)在完成前k 个作业时,设机器A 工作了x 时间,则机器B 最小的工作时间是x 的一个函数。

设F[k][x]表示完成前k 个作业时,机器B 最小的工作时间,则)}](1[,)](1[m in{)]([k k a x k F b x k F x k F其中k b x k F )](1[对应第k 个作业由机器B 来处理(完成k-1个作业时机器A 工作时间仍是x ,则B 在k-1阶段用时为)](1[x k F );而)](1[k a x k F 对应第k 个作业由机器A 处理(完成k-1个作业,机器A 工作时间是x-a[k],而B 完成k 阶段与完成k-1阶段用时相同为)](1[k a x k F )。

则完成前k 个作业所需的时间为)}]([,max{x k F x 1)当处理第一个作业时,a[1]=2,b[1]=3;机器A 所花费时间的所有可能值围:0 x a[0]. x<0时,设F[0][x]= ∞,则max(x, ∞)= ∞; 0 x<2时,F[1][x]=3,则Max(0,3)=3, x 2时, F[1][x]= 0,则Max(2,0)=2;2)处理第二个作业时:x 的取值围是:0 <= x <= (a[0] + a[1]), 当x<0时,记F[2][x] = ∞;以此类推下去(思路三)假定n 个作业的集合为 n S n ,,2,1 。

设J 为n S 的子集,若安排J 中的作业在机器A 上处理,其余作业在机器B 上处理,此时所用时间为J S j j Jj j b a J T \,max )(, 则双机处理作业问题相当于确定n S 的子集J ,使得安排是最省时的。

即转化为求J 使得)}({min J T nS J 。

若记 1,,2,11 n S n ,则有如下递推关系:J S j j n J j j S J J S j j J j j n S J I S j j I j j S I b b a b a a b a n n n \\\,max min ,,max min min ,max min 11--(思路四)此问题等价于求(x 1,……x n ),使得它是下面的问题最优解。

min max{x 1a 1+……x n a n ,(1-x 1)b 1+……+(1-x n )b n } x i =0或1,i=1~n基于动态规划算法的思想,对每个任务i ,依次计算集合S (i)。

其中每个集合中元素都是一个3元组(F 1,F 2,x )。

这个3元组的每个分量定义为 F 1:处理机A 的完成时间 F 2:处理机B 的完成时间 x :任务分配变量。

当x i =1时表示将任务i 分配给处理机A ,当x i =0时表示分配给处理机B 。

初始时,S (0)={(0,0,0)}令F=按处理时间少的原则来分配任务的方案所需的完成时间。

例如,当(a 1,a 2,a 3,a 4,a 5,a 6)=(2,5,7,10,5,2),(b 1,b 2,b 3,b 4,b 5,b 6)=(3,8,4,11,3,4)时,按处理时间少的原则分配任务的方案为(x 1,x 2,x 3,x 4,x 5,x 6)=(1,1,0,1,0,1) 因此,F=max{2+5+10+2,7+5}=19。

然后,依次考虑任务i ,i=1~n 。

在分配任务i 时,只有2种情形,x i =1或x i =0。

此时,令S(i)={S(i-1)+(a i,0,2i)}U{S(i-1)+(0,b i,0)}在做上述集合并集的计算时,遵循下面的原则:①当(a,b,c),(d,e,f)ЄS(i)且a=d,b<=e时,仅保留(a,b,c);②仅当max{a,b}<=F时,(a,b,c)ЄS(i)最后在S(n)中找出使max{F1,F2}达到最小的元素,相应的x即为所求的最优解,其最优值为max{F1,F2}。

当(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2),(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)时, 按处理时间少的原则分配任务的方案为(x1,x2,x3,x4,x5,x6)=(1,1,0,1,0,1)因此,F=max{2+5+10+2,7+5}=19。

S(0)={(0,0,0)};S(1)={(2,0,2),(0,3,0)}S(2)={(7,0,6),(5,3,4),(2,8,2),(0,11,0)}S(3)={(14,0,14),(12,3,12),(9,8,10), (7,4,6), (5,7,4),(2,12,2),(0,15,0)}S(4)={(19,8,26), (17,4,22),(15,7,20),(12,12,18),(14,11,14),(9,19,10),(7,15,6),(5,18,4)}S(5)={ (19,11,46), (12,15,38), (19,11,26), (17,7,22), (15,10,20),(12,15,18),(14,14,14),(7,18,6)}S(6)={ (14,15,102),(19,7,86),(17,10,84),(14,15,82), (9,18,70),(12,19,38), (15,14,20),(12,19,18)} max(F1,F2)最小的元组为(14,15,102), (14,15,82), (15,14,20)所以,完成所有作业最短时间是15,安排有三种:(1,1,0,0,1,1),(1,0,0,1,0,1),(0,1,0,1,0,0)(思路五)C++ 源代码如下:#include<iostream>using namespace std;const int MAXS = 70;const int MAXN = 10;bool p[MAXS][MAXS][MAXS];int a[MAXS],b[MAXS];int schduleDyn(int * a,int * b,int n,int mn){ int i,j,k;//===========数组初始化===================for(i = 0; i <= mn; i++)for(j = 0; j <= mn; j++){ p[i][j][0] = true;for(k = 1 ; k <= n; k++)p[i][j][k] = false;}//===========动态递归=============for(k = 1; k <= n; k ++)for(i = 0; i <= mn; i++)for(j = 0; j <= mn; j++){ if( (i - a[k-1]) >= 0)p[i][j][k] = p[i - a[k-1]][j][k-1];if( (j - b[k-1]) >= 0)p[i][j][k] = (p[i][j][k] | p[i][j-b[k-1]][k-1]);}//================求结果=====================int rs = mn;int temp = 0;for(i = 0; i <= mn; i++)for(j = 0; j <= mn ; j++){if(p[i][j][n]){ temp = i > j ? i : j;if(temp < rs)rs = temp;}}return rs;}void main(){int i,n,m = 0,mn = 0;//=============初始化========================cin >> n;for(i = 0; i < n; i++){ cin >> a[i];if(a[i] > m)m = a[i];}for(i = 0; i < n; i++){cin >> b[i];if(b[i] > m)m = b[i];}mn = m * n;//=========动态规划求解=================cout << schduleDyn(a,b,n,mn) << endl;system("pause");}对于例子: n = 6 ;(a1,….,a6) = (2 5 7 10 5 2),(b,1…,b6) = (3 8 4 11 3 4); 由于求解过程比较繁锁,这里只说个大概算法执行过程,首先,用p[i][j][k],记录下对于第k 个作业,能否在对于a机器是i时间以,对于b机器是j时间以完成,如果能,则把p[i][j][k]设为true.经过了设置后,求对于n个作业的所有可能的值为p[i][j][n],对min(max(i,j)),结果为15.即为所得到的结果.3.考虑下面特殊的整数线性规划问题ni x b xa x c i ni iini ii 1},2,1,0{,max 11试设计一个解此问题的动态规划算法,并分析算法的时间复杂度。

相关主题