else {max2= A[high];max1=A[low];}}
else
{
SecondElement(A[low..high],x1,x2);
if(x1<=A[n]) { max2=max1; max1=A[n];}
else if(x2>=A[n]) { max2=x2; max1=x1; }
else { max2=A[n]; max1=x1; }
}
}
该算法的时间复杂度满足如下递归方程:T(n)=T(n-1)+2;T(2)=1。解得T(n)=2n-3。
作业二
一、名词解释:
1.MST性质:G=(V,E)是连通带权图,U是V的真子集。如果(u,v)E,且uU,vV-U,且在所有这样的边中,(u,v)的权c[u][v]最小,那么一定存在G的一棵最小生成树,它以(u,v)为其中一条边。这个性质称为MST性质。
2.子问题的重叠性质:递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次,这种性质称为子问题的重叠性质。
二、简答题:
1.简述动态规划算法求解的基本要素。
动态规划算法求解的基本要素包括:
(1)最优子结构是问题能用动态规划算法求解的前提;
(2)动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果,即重叠子问题。
2.备忘录方法和动态规划算法相比有何异同?简述之。
备忘录方法是动态规划算法的变形。与动态规划算法一样,备忘录方法用表格保存已解决的子问题的答案,在下次需要解此问题时,只要简单地查看该子问题的解答,而不必重新计算。
备忘录方法与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同的子问题的重复求解,而直接递归方法没有此功能。
3.贪心算法求解的问题主要具有哪些性质?简述之。
贪心算法求解的问题一般具有二个重要的性质:一是贪心选择性质,这是贪心算法可行的第一个基本要素;另一个是最优子结构性质,问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
三、算法编写及算法应用分析题:
1.设计求解如下最大子段和问题的动态规划算法。只需给出其递推计算公式即可。
最大子段和问题:给定由n 个整数(可能为负整数)组成的序列a1a2 … an,求该序列形如Σi≤k≤j ak的子段和的最大值。当所有整数均为负整数时定义其最大子段和为0。依次定义,所求的最优值为max{0, max1≤i≤j≤n Σi≤k≤j ak }。
答:下面给出求解该问题的动态规划算法中的递推计算公式。
记 b(j)=max1≤i≤j{Σi≤k≤j ak },1≤j≤n,则所求最大子段和为max1≤j≤nb(j)。而计算b[j]的递推计算公式为:
b(0)=0 b(j)=max{b(j-1)+aj, aj}, 1≤j≤n。
该算法的时间复杂度为O(n);空间复杂度为O(n)。
2.关于多段图问题。设G=(V,E)是一个赋权有向图,其顶点集V被划分成k>2个不相交的子集Vi:,其中,V1和Vk分别只有一个顶点s(称为源)和一个顶点t(称为汇),图中所有的边(u,v),,。求由s到t的最小成本路径。
(1)给出使用动态规划算法求解多段图问题的基本思想。
(2)使用上述方法求解如下多段图问题。
解:(1)基本思想:设P(i,j)是从Vi中的节点j到汇点t的最小成本路径,Cost(i,j)是其成本。则。边界条件是(1)若h=t,则Cost(h,t)=0;(2)Cost(k-1,j)=c(j,t)。
(2)求解过程可以表示为:
其中每个节点标示的序偶(p,q)中,p表示节点到t的成本,q表示后继节点的编号。从而,最优路径为:1271012和1361012,成本为16。
3.最优二元归并问题:已知将两个分别包含 a 个和b 个记录的已分类文件归并在一起得到一个分类文件需作a+b 次记录移动。现有n 个已分类文件F1,F1,⋯,Fn,它们的记录个数分别为l1, l2,⋯, ln。现在考虑使用二元归并模式将这n 个文件归并成一个分类文件,要求记录移动次数最少。设计一个贪心算法来求解一种最优的二元归并(即记录移动次数最少的二元归并)。
答:(1)贪心准则:依次将文件序列中记录最少的两个文件进行归并成一个文件,直到文件序列中只剩下一个文件为止。
(2)贪心算法:
Algorithm BINARYTREE
输入:n 个单结点二元树列表L,这些棵树的根结点的权分别为l1, l2,⋯, ln。
输出:一棵最优二元归并树L
Begin
For i←1 To n-1 Do
GETNODE(T) //该过程产生一个新结点T
LCHILD(T)←LEAST(L) //将表L中其根权最小的树取出并作为T 的左孩子
RCHILD(T)←LEAST(L) ////将表L 中其根权最小的树取出并作为T的右孩子
WEIGHT(T)←WEIGHT(LCHILD(T))+WEIGHT(RCHILD(T))
Repeat
Return(L)
End.
4.带限期的作业调度问题:n 个作业需要在一台机器上处理,每个作业可在单位时间内完成。每个作业i 都有一个截止期限di>0(di 为整数),当且仅当作业i 在它的截止期限之前被完成,获得pi>0 的效益。一种可行的调度方案为n 个作业的一个子集J,其中J 中的每个作业都能在各自的截止期限内完成。该可行调度方案的效益是J 中作业的效益之和。试设计贪心算法求效益最大的可行调度方案(即最优调度方案)。
答:(1)贪心准则:从J=∅开始,不断添加作业到J 中。每次加入J 的作业是保证J 是可行的
前提下使得J 中效益达到最大。即,按照pi 由大到小的次序来考虑作业。
(2)贪心算法:
Algorithm JOBSCHEDULE
输入:n 个作业的截至期限d1,d2,⋯, dn 和相应的效益值p1, p2,⋯, pn。
输出:效益最大可行调度方案J(作业子集)
Begin
将作业按照效益值排序使得p1≥p2≥⋯≥pn,相应的截至期限为d1, d2,⋯, dn。
J={1}
For i←2 To n Do
If (J∪{i}中所有作业都能在它们的截至期限内完成) Then
J←J∪{i}
Endif
Repeat
End.
作业三
一、名词解释:
1.多机调度问题:要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。同时约定每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业。
2.优先队列式分支限界法:是将活结点表组织成一个优先队列,按照优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前扩展结点。在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。
二、简答题:
1.简述回溯法的基本思想。
回溯法的基本做法是搜索,在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
2.简要分析分支限界法与回溯法的异同。
(1)求解目标:回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
(2)搜索方式的不同:回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
3.常见的分支限界法有哪些?简述之。
常见的两种分支限界法:
(1)队列式(FIFO)分支限界法:将活结点表组织成一个队列,并按照队列的先进先出(FIFO)原则选取下一个结点为扩展结点;
(2)优先队列式分支限界法:将活结点表组织成一个优先队列,按照优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前扩展结点。在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。
三、算法编写及算法应用分析题:
1.分派问题一般陈述如下:给n 个人分派n 件工作,把工作j 分派给第i 个人的代价是COST(i,j)(非负实数)。要求设计一个回溯算法,在给每个人分派一件不同工作的前提下使得总代价最小。按照回溯法求解问题的基本步骤,请你完成几个任务:
(1)给出解的一般形式,写出解空间。
(2)以 n=4 为例画出表示解空间的状态空间树。并指出树中哪些结点是解结点?
(3)提出一个在深度优先搜索状态空间树时用于剪枝的剪枝函数(用文字描述)。
答:(1)解的形式:(x1,x2,⋯,xn),其中xi=1,2,⋯,n 表示给第i 个人安排的工作号。解空间为{(x1,x2,⋯,xn)| xi=1,2,⋯,n, 1≤i≤n}。
(2)n=4 的状态空间树为高度为4 的满4 叉树。图<略>。图中叶结点是解结点。
(3)剪枝操作有二。一是基于约束条件的剪枝操作:若当前给第i 个人分配的工作号已被分配,则剪枝。另一个是基于目标值的剪枝操作:若当前给第i 个人分配的工作号未被分配,但是目前已分配的总成本大于或者等于已有的某个分配方案的成本则剪枝。
2.设计一个回溯算法来求解k-着色问题:给定无向图G=, 要求使用k 种颜色来给图中每个结点着色(每个结点使用k 种颜色之一),使得没有两个相邻的结点颜色相同。(1)给出解向量的形式,并画出当n=3,k=3 时的搜索树。(2)给出剪枝操作。
(3)最坏情况下你的算法在搜索树上会生成多少个结点?分析算法的时间复杂度。
答:(1)解向量的形式为(x1,x2,⋯,xn),其中xi=1,2,3 表示图中第i 个结点所着的颜色(1≤i≤n)。当n=3,k=3时搜索树为高度为3 的满3 叉树。
(2)剪枝操作如下:当搜索到结点X=(x1,x2,⋯,xi)时,如果图中第i结点所着色xi 与前1,2,⋯,i-1结点所作的颜色无冲突,即图中这些结点中与结点i 有边相连的结点所着颜色都不是xi,则不剪枝,否则剪枝(即搜索跳过对子树X的搜索)。
(3)该算法的最坏时间复杂度是与搜索树中结点个数和在每个结点处花费的时间都有关。搜索树中结点个数为O(kn),而在搜索中每个结点处花费的时间为O(n),因此最坏时间复杂度是O(nkn)。
3.对于下图使用Dijkstra算法求由顶点a到其他各个顶点的最短路径。并给出求各个顶点对之间的最短路径的算法思想。
解:用V1表示已经找到最短路径的顶点,V2表示与V1中某个顶点相邻接且不在V1中的顶点;E1表示加入到最短路径中的边,E2为与V1中的顶点相邻接且距离最短的路径。
步1 V2 E1 E2
1. {a} { { {ab}
2{a,b} { {bd}
3. {c,f} {ab,bd} {dc,df}
4. { {ab,bd} {df}
5. {a,b,c,d,f} {e} {ab,bd,dc,df} {fe}
6. {a,b,c,d,e,f} {g} {ab,bd,dc,df,fe} {eg}
7. {a,b,c,d,e,f,g} { {ab,bd,dc,df,fe,eg} {gh}
8. {a,b,c,d,e,f,g,h} { {ab,bd,de,df,fe,eg,gh} {}
结果:从a到h的最短路径为,权值为18。
求所有顶点对之间的最短路径可以使用Dijkstra算法,使其起始节点从a循环到h,每次求起始节点到其他节点的最短路径,最终可以求得所有顶点对之间的最短路径。
4.设计一个求解下列最大完全子图问题的回溯算法。只要求叙述清楚算法的主要要素,并指出算法的最坏时间复杂度。
最大完全子图问题:给定无向图G,求出G中顶点个数最多的完全子图。
答:求解此问题的一个回溯算法的要素如下:
(1)问题解的形式为(x1,x1,⋯,xn),其中xi=0 或1,n 为图G 中顶点个数。因此,搜索树是满二叉树。(x1,x1,⋯,xn)表示一个完全子图中的顶点,对于任意i(1≤i≤n),xi=1 表示第i 个顶点在该完全子图中,而xi=0 则表示第i 个顶点不在该完全子图中。
(2)剪枝办法1:当将第 i 个结点考虑到当前完全子图中即xi=1 时是不可行的 结点i 不是与任何满足xj=1(1≤j≤i-1)的结点j 均有边相连。
(3)剪枝办法2:当将第 i 个结点考虑到当前完全子图中即xi=1 时不可能产生更好结果 在结点i+1,i+2,⋯,n 中与(x1,x1,⋯,xi)中值为1 的每个分量所对应的结点均有边相连的结点个数+向量(x1,x1,⋯,xi)中值为1 的分量的个数≤当前已得到的最大完全子图的结点个数。当前已得到的最大完全子图的结点个数最初可以置为 1,然后随着搜索的进行不断更新。该算法的最坏时间复杂度是与搜索树中结点个数和在每个结点处花费的时间都有关。搜索树中结点个数为O(2n),而在搜索中每个结点处花费的时间为O(n2),因此最坏时间复杂度是O(n22n)。