哈工大算法设计与分析期末试题解析

试题内容来自https://www.cnblogs.com/fyunaru/archive/2019/07/02/11123804.html

本文基于该试题添加了解析,仅供参考

 

一、判断题(10 * 2 分)

1.A*算法一定可以得到最优解。正确

A*算法定义:

(1)使用最佳优先策略搜索

(2)节点n的代价函数:f(n)=g(n)+h(n),g(n)是起点到节点n的最短路径代价,h(n)是节点n到目标节点的估计代价

(3)h(n)<=h*(n),h(n)表示节点n到终点的估计代价,h*(n)表示节点n到终点的实际代价(保证A*算法一定得到最优解的条件)

(4)当选择到的节点是目标节点时,算法停止,返回一个最优解

 

A*算法代价函数估计公式:f(n)=g(n)+h(n)

g(n)=0时,仅计算任意节点n到目标节点的启发函数,而不计算节点到节点n的最短距离,算法转化为使用贪心策略的最佳优先搜索,速度最快,但可能找不到最优解;

h(n)<=h*(n)时,一定可以求出最优解,h(n)越小,需要计算的节点越多,算法效率越低,常见的启发函数有曼哈顿距离、欧几里得距离等

h(n)=0时,仅计算起点到任意节点n的最短距离,而不计算任何启发函数h(n),转化为单源最短路径问题,即Dijkstra算法,需要计算最多的节点

 

2.调试程序可以证明算法的正确性。错误

算法的正确性定义:对于每一个输入都最终停止,而且产生正确的输出

算法的正确性证明:(1)证明算法对所有输入都终止(2)证明对每个输入都产生正确结果

程序调试!=程序正确性证明:程序调试只能证明程序有错,不能证明程序无错误

循环不变量方法:证明主要结构是循环结构的算法的正确性

 

3.dijkstra算法是贪心算法。

算法维护两个顶点集合S和Q。集合S保留所有已知实际最短路径值的顶点,而集合Q则保留其他所有顶点。

集合S初始状态为空,而后每一步都有一个顶点从Q移动到S。这个被选择的顶点是Q中拥有最小的d[u]值的顶点。

当一个顶点u从Q中转移到了S中,算法对u的每条外接边w(u,v)进行松弛。

 

4.如果一个基于比较的排序算法的时间复杂性是Ω(nlogn),那么他可能是基于比较算法中时间复杂性最低的算法。正确

假设需要排序的数有N个,N个数有N!种不同的排序情况,即基于比较的排序算法的判定树有N!个叶子节点。

比较次数最少为log(N!)=O(NlogN)

 

 

5.一个关于堆排序的插入和删除操作的时间复杂性的问题。(具体怎么问忘了)

原地堆排序:

(1)创建一个堆H[0:n]

(2)把堆首与堆尾互换

(3)把堆的尺寸减1,并调用堆调整,将新的堆顶端元素调到合适位置

(4)不断重复(2)(3)两个步骤,直到堆的尺寸为1

 

堆的插入操作:将新元素插入堆尾,已知新元素的父节点到根节点是一个有序的序列,将新元素插入到该序列中,可以视为直接插入排序。(时间复杂度O(logn))

堆的删除操作:将堆顶元素与堆尾元素调换位置;堆尺寸减1,对新堆进行堆调整。(时间复杂度O(logn))

 

6.一个问KMP算法的时间复杂性的问题。

KMP算法可在一个主文本字符串S内查找一个词W(或称模式串)的出现位置

如果文本串的长度为 n,模式串的长度为 m,那么匹配过程的时间复杂度为 O(n),算上计算 next 的 O(m) 时间,KMP 的整体时间复杂度为 O(m + n)

 

二、简答题(5 * 4分)

1.一个master定理的题目(很类似于ppt上的一道例题)应该是T(n) = 3T(n/4) + n^(1/2) 

https://zh.wikipedia.org/wiki/%E4%B8%BB%E5%AE%9A%E7%90%86

a=3,b=4

f(n)=n^(1/2) = O(n^(log_4(3-1))),符合情形一的情况

T(n)=Theta(n^(log_4(3)))

 

2.一个非常简单的复杂函数阶的证明,已知fx = O(g(x)), gx = o(hx),证明 fx = o(hx)

证明:

f(x)=O(g(x)) => 对于任意的c1,c2>0,x > x0时,c1*g(x) <= f(x) <= c2*g(x)

g(x)=o(h(x)) => 对于任意的c>0,x > x1时,g(x) < c*h(x)

当x>max(x0,x1)时,f(x) <= c2*g(x) => f(x) < c2*c*h(x) = C*h(x),其中C=c2*c

因此f(x) = o(h(x))

 

3.写出0-1背包问题的输入规模和时间复杂性

输入:C>0, w_i>0, v_i>0, 1<=i<=n

输出:(x_1,x_2,...,x_n), x_i in {0, 1},满足sum_{1=<i<=n}w_i*x_i<=C},

 

输入规模:一个问题的输入规模是保存输入数据所需要的bit位数。

输入规模:x = logC

 

动态规划解法:设dp[i][j]代表从0-i中挑选一些整数,每个物品只能使用一次,是否能够恰好填满容量为j的背包

for i = 1 to n:

  for j = 0 to C:

    dp[i][j] = dp[i - 1][j]  

    if nums[i] == j:

      dp[i][j]=True

      continue

    if nums[i] <  j:

      dp[i][j]=dp[i-1][j] or dp[i-1][j-nums[i]] 

 

标准多项式时间复杂度:对于一个问题,在输入规模为x的情况下,如果一个算法能够在O(x^k)时间内解决此问题,则我们称此算法是多项式时间的,其中k为一常数。

动态规划解法时间复杂度:O(nC) = O(n*(2^x))

 

传统时间复杂度与标准时间复杂度对比

相似:图论、链表、数组、树等问题

不同:数论问题(例如素数判定算法,传统时间复杂度O(n),输入规模x=logn,标准时间复杂度O(2^x))

若一个算法的传统时间复杂度为多项式的,但标准时间复杂度不是多项式的,则算法为伪多项式时间复杂度算法

 

4.说明平摊分析的目的,以及任举一种平摊分析方法说明其大致思想,以及使用时需要注意的点

 

 

三、(8分)

一个最大流的问题,给了一个最大流的图‘

第一问要求画出某一步之后的余图

第二问要求找出一条可以使流量增加1的増广路径

第三问要求给出一个最小割

 

 

图(a)为一个流网络,图(b)展示了它的余图 

符号定义:flow(a)代表边a的流量,c(a)代表边a的容量,s-t路径是指从起点s通往目标点t的任意一条路径

余图:余图(residual graph)的顶点和原图一样,如上图右所示,它包含两类弧:(1)原图的未饱和弧;(2)原图flow(a)>0的弧的反向弧。

增广路径:一条满足flow(a)<c(a)弧构成的s-t路径,上图(b)中s-v2-v3-t,容量为4的路径即为增广路径

流网络的割:流网络G中的一个割(S, T)将结点集合V划分为S和T=V-S两个集合,满足s in S,t in T

 

推论:流与割的弱对偶关系

给定流网络 G=(V,E),s是源,t是汇. 设f是G上的一个流,S,T是G的任意一个割,则f(S,T)=|f|.

给定流网络 G=(V,E). 设f是G上的一个流,(S,T)是G的任意一个割,则|f| <= c(S,T)

最小割:任意流不大于任意割,最大流等于最小割。

 

最大流算法(Ford-Fulkerson算法):

(1)建立原图流为0的余图;

(2)在余图中找出任意的s-t路径,并按该路径找出原图允许的最大流K:

  • 最大流K根据弧的容量减去已有的流;
  • 对余图的正向弧,原图的流加上K;
  • 对余图的反向弧,原图的流减去K。

(3)更新余图,重复上述过程,直到余图不存在s-t路径。

 

5分钟看懂Ford-Fulkerson算法:https://www.youtube.com/watch?v=Tl90tNtKvxs

 

四、(7分)

给出一个加权有向图,要求用A*算法把整个过程写一遍,并给出最后所得的最短路径。

 

A*算法的通俗介绍(https://www.redblobgames.com/pathfinding/a-star/introduction.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

将加权有向图转为解空间树,逐步写出当前节点的拓展节点的g(n)、h(n)、f(n)并标在图的节点旁边

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

五、(20分)

分治算法的题,是作业题上的一道原题。
原题如下:

 

 

第一问写出算法思想

第二问写伪代码

第三问分析时间复杂度

 

算法思想:

首先利用O(nlogn)的排序算法对S进行排序;

然后循环遍历S的每一个元素S[i],利用二分查找判断S中是否包含x-S[i],该步二分查找复杂度为O(logn),因此循环复杂度为O(nlogn)

综上算法的整体复杂度为O(nlogn)

 

六、(15分)

贪心算法的题。(这道题我真是无力吐槽,考场上没看懂怎么写,考完之后问了几个同学都说贪心思想和算法随便写的,且每个人写的都不一样,后来问老师那个题怎么写,老师说只要言之有理都算对,,,)

题目大概写一下吧,反正我觉得这题出的真差,你们复习的时候可以自己找点别的贪心算法的题做。

有一条环形公路,公路上有n个加油站,一辆油箱容量无限大的汽车在这条路上行驶,每个加油站所能给车加的最大油量为si,车在每两个加油站之间行驶耗得油为ci。要求写出一个贪心算法,让这个车选择一个加油站作为起始点,能够成功绕这个环形公路一圈并回到起始点,如果没有这样的加油站,则返回-1,有则返回所选择的起始加油站的编号。

第一问写贪心思想

第二问证明贪心思想

第三问伪代码

第四问时间复杂度

 

贪心思想:

贪心思想的证明:

 

 

七、(10分)

动态规划的题。比较简单,多做几道动态规划的题应该就可以做出来了。

题目大致如下:

给定如图所示的一个树状图,每个节点上都标有该点权值,该树共有5层,从第一层的节点进入,从第五层的节点出来,要求找出一条长为4(即通过了5个节点)的路径,使得该条路径所经过的5个节点和最小。

 

图像大致如下:

 

 

posted @ 2020-07-20 22:02  郝丁魁  阅读(5106)  评论(0编辑  收藏  举报