目录
优先队列式分枝限界法选取扩展结点的原则是( )。
A.先进先出
B.后进先出
C.结点的优先级
D.随机
答案:C
下列算法中通常以自底向上的方式求解最优解的是( )。
A.备忘录法
B.动态规划法
C.贪心法
D.回溯法
答案:B
一个问题可用动态规划法或贪心法求解的关键特征是问题的( )。
A.贪心选择性质
B.重叠子问题
C.最优子结构性质
D.定义最优解
答案:C
Dijkstra算法是利用( )实现的算法。
A.分治算法
B.动态规划算法
C.贪心算法
D.回溯法
答案:C
快速排序算法是根据( )思想设计的算法。
A.回溯法
B.动态规划法
C.分治算法
D.贪婪算法
答案:C
若分治法的时间递归式是:
T(n) = aT(n/b) + O(n^c)
那么把二分查找法看成分治法时,上述公式中的a,b,c分别是--A.2,2,1
B.1,2,1
C.2,2,0
D.1,2,0
答案:D
装载问题是0-1背包问题的特例,原因是_____。
A.一艘船装载总重量尽量大的集装箱以后,另一艘船就可以装重量尽量少的集装箱。
B.一艘船装载总重量尽量大的集装箱以后,就可以知道另一艘船能不能装下其余的集装箱。
C.这两个问题都是以集装箱不可分割作为前提。
D.这两个问题都是尽可能装载重量更多的集装箱。
答案:B
对n皇后问题求一个可行解,若n为偶数,那么已经满足“同一行、同一列都不能有两个皇后”约束条件下的解空间大小(最精确的)是_______。
A.不超过(2n)
B.不超过(2n/2)
C.不超过(n!)
D.不超过(n!/2)
答案:D
关于分治算法描述正确的是
A.分治算法通常用于解决那些可以分解为多个相似子问题的问题。
B.归并排序不是分治算法的一种。
C.分治算法不能用来排序
D.分治算法的时间复杂度总是O(n log n)。
答案:A
某算法的时间复杂度是O(n2),表明该算法的( )。
A.问题规模是n2
B.执行时间等于n2
C.执行时间与n2成正比
D.问题规模与n2成正比
答案:C
以下答案仅代表个人想法,仅供参考
8-1 计算题-时间复杂度分析
已知一个分治算法耗费的计算时间T(n),T(n)满足如下递归方程:
请求解此递归方程。(logn为
的简记)
解:
8-2 动态规划法与贪心法的异同
简述动态规划法与贪心法的异同。
解:
同:
贪心法和动态规划算法都要求问题具有最优子结构性质
异:
动态规划:依赖于子问题的解,自底向上或自顶向下求解
贪心法:不依赖于子问题的解,自顶向下求解
动态规划的条件:子问题的重叠性质
贪心法的条件:最优子结构性质,贪心选择性质
8-3 矩阵连乘
利用动态规划法计算矩阵连乘积A1A2A3A4A5的最佳求积顺序(即:数乘次数最少的计算次序),各矩阵的维数分别为:
(要求给出计算步骤)
解:
递推式m[i][j]=m[i][k]+m[k+1][j]+pi-1*pk*pj
m数组为第i个矩阵到第j个矩阵的最小乘法执行次数
s为断开位置即为每个式子里的k
计算顺序(((A1A2)(A3A4))A5)
执行乘法次数为1655
8-4 最大子数组和
已知由8个整数构成的序列:(12,-4,7,-5,16,-4,8,7)。
(1)请用分治法求最大子数组和(请给出分解与合并的具体步骤及子数组和);
(2)请用动态规划法求最大子数组和(请给出递推式、计算过程及最后的子数组及子数组和);
(3)请根据该题,对比分治法与动态规划法的异同(请给出不少于4个异同点)。
解:
(1)
分解步骤:
1、将序列分为两半:左区间部分为(12, -4, 7, -5),右区间部分为(16, -4, 8, 7)。
2、递归地求左区间和右区间的最大子数组和。
3、求跨越两半部分的最大子数组和。
合并步骤:
1、左区间的最大子数组和
分解为(12, -4)和(7, -5)
(12, -4)的最大子数组和为12
(7, -5)的最大子数组和为7
跨越(12, -4)和(7, -5)的最大子数组和为12 + (-4) + 7 = 15
左半部分的最大子数组和为15
2、右区间的最大子数组和
分解为(16, -4)和(8, 7)
(16, -4)的最大子数组和为16
(8, 7)的最大子数组和为15
跨越(16, -4)和(8, 7)的最大子数组和为16 + (-4) + 8 + 7 = 27
右半部分的最大子数组和为27
3、跨越两个区间的最大子数组和:
从左区间的末尾开始向左求最大子数组和:12 + (-4) + 7 + (-5) = 10
从右区间的开始向右求最大子数组和:16 + (-4) + 8 + 7 = 27
跨越两半部分的最大子数组和为10 + 27 = 37
最大子数组和为37,最大子数组为(12,-4,7,-5,16,-4,8,7)
(2)
设dp[i]表示前i个元素中的最大子数组和
递推式为
dp[0]=0
dp[i]=max(dp[i-1]+a[i],a[i])
计算过程
初始化dp[0]=0
计算dp[1] = max(dp[0] + 12, 12) = 12
计算dp[2] = max(dp[1] + (-4), -4) = 8
计算dp[3] = max(dp[2] + 7, 7) = 15
计算dp[4] = max(dp[3] + (-5), -5) = 10
计算dp[5] = max(dp[4] + 16, 16) = 26
计算dp[6] = max(dp[5] + (-4), -4) = 22
计算dp[7] = max(dp[6] + 8, 8) = 30
计算dp[8] = max(dp[7] + 7, 7) = 37
最大子数组和为37,最大子数组为(12,-4,7,-5,16,-4,8,7)
(3)
两者的共同点是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
两者的不同点如下:
适合用动态规划法求解的问题,分解得到的各子问题往往不是相互独立的(重叠子问题性质),而分治法中的子问题相互独立;
另外,动态规划法用表保存已求解过的子问题的解,再次碰到同样的子问题时不必重新求解,只需查询答案,故可获得多项式级时间复杂度,效率较高,而分治法中对于每次出现的子问题均求解,导致同样的子问题被反复求解,故产生指数增长的时间复杂度,效率较低。
8-5 旅行商问题
用分支限界法求解旅行商问题,如图所示,n=4,城市1为售货员所在的城市,请画出最终的搜索树。
解:
旅行商问题要求,从某一点开始行走,经过其他所有的点,并回到初始点的最短路径
路径上的数字为下一个走到的城市,结点上的数字为当前走过的城市所需走的距离之和
如图
搜索所有路径情况
1,2,3,4,1 距离为59
1,2,4,3,1 距离为66
1,3,2,4,1 距离为25
1,3,4,2,1 距离为66
1,4,2,3,1 距离为25
1,4,3,2,1 距离为59
最短路径为
1,3,2,4,1 距离为25
1,4,2,3,1 距离为25
8-6 算法设计题-0-1背包问题
(提示:算法设计题,要先用文字阐述算法设计思想,然后用伪代码的形式给出算法,最后要进行算法时间复杂度分析,另如果用到贪心算法,则需要分析其是否具体贪心选择性质)
0-1背包问题∶给定n种物品和一背包,物品i的重量是wi,其价值为vi,背包的容量为C.问应该如何装入背包,使得背包中物品的总价值最大?写出用回溯法解决该问题的算法。
解:
对于01背包问题使用回溯算法,每个物品有选和不选两个状态,递归搜索所有可能的情况进行搭配
对于01背包问题使用回溯算法,每个物品有选和不选两个状态,递归搜索所有可能的情况进行搭配
// 定义全局变量 定义 v[1...n], w[1...n], st[1...n], jl[1...n] 定义 n, m, res, sum, zl 函数 dfs(x) 如果 x > n 如果 res < sum 设置 res = sum 设置 zl = 0 对于 i 从 1 到 n 设置 jl[i] = st[i] 如果 st[i] = 1 增加 zl 以 v[i] 结束如果 结束循环 结束如果 返回 结束如果 对于 i 从 1 到 n + 1 如果 i = n + 1 调用 dfs(x + 1) 退出循环 结束如果 如果 st[i] = 0 且 m - v[i] >= 0 设置 st[i] = 1 减少 m 以 v[i] 增加 sum 以 w[i] 调用 dfs(x + 1) 设置 st[i] = 0 增加 m 以 v[i] 减少 sum 以 w[i] 结束如果 结束循环 结束函数 // 从输入读取n和m的值 读取 n, m // 读取每个物品的价值和重量 对于 i 从 1 到 n 读取 v[i], w[i] 结束循环 // 调用深度优先搜索函数 调用 dfs(0) // 输出选择的物品编号 对于 i 从 1 到 n 如果 jl[i] 不等于 0 输出 i 结束如果 结束循环 // 输出最大价值和总重量 输出换行 输出 res, " ", zl
总共有n个物品,每个物品有选和不选两个状态,所以时间复杂度为O(2^n)
由于需要更新记录下选取的物品编号所以时间复杂度为O(n2^n)
8-7 算法设计题-活动安排
(提示:算法设计题,要先用文字阐述算法设计思想,然后用伪代码的形式给出算法,最后要进行算法时间复杂度分析,另如果用到贪心算法,则需要分析其是否具体贪心选择性质)
某体育馆有一羽毛球场出租,现在总共有10位客户申请租用此羽毛球场,每个客户所租用的开始时间和结束时间如下表所示,其中s(i)表示开始租用时间,f(i)表示结束租用时间:
同一时刻,该羽毛球场只能租给一位客户,请设计一个租用安排方案,在这10位客户里面,使得体育馆尽可能满足多位客户的需求,并算出针对上表的10个客户申请,最多可以安排几位客户申请?
解:
本题使用贪心算法,由于一次只能租给一位客户,所以需要尽早开始尽早使租用时间结束,我们需要按结束时间从小到大排序,排序后如下
排序后如下:
伪代码:
首先记录开始时间和结束时间在q数组中,q数组的数据类型为包含两个int类型的结构体
开始 // 输入元素个数 n 输入 n // 初始化结构体数组 q,用于存储每对开始时间和结束时间 对于 i = 1 到 n 输入 q[i].a 和 q[i].b 结束 // 使用快速排序进行排序 对 q[1] 到 q[n] 进行排序 // 初始化变量 sum = 0 dq = 0 // 遍历排序后的数组 q 对于 i = 1 到 n 如果 i = 1 dq = q[i].b sum = sum + 1 否则如果 q[i].a >= dq dq = q[i].b sum = sum + 1 结束如果 结束 //输出最多能安排的客户 输出 sum 结束
由于存在排序,使用快速排序的平均时间复杂度为O(nlogn),检查客户所用的时间复杂度为O(n),所以该算法的时间复杂度为O(nlogn)
按照上述策略,我们选择了以下客户:3, 6, 7, 9,所以最多可以安排4位客户的申请。
8-8 算法设计题-找零钱问题
(提示:算法设计题,要先用文字阐述算法设计思想,然后用伪代码的形式给出算法,最后要进行算法时间复杂度分析,另如果用到贪心算法,则需要分析其是否具体贪心选择性质)
小明是一个销售员,客人在他的地方买了东西,付给了小明一定面值的钱之后,小明需要把多余的钱退给客人,客人付给了小明n,小明的东西的售价为m,小明能退回给客人的面额只能为[100,50,20,10,5,2,1]的组合,设计一种策略,使小明想要使找出去纸币张数最小。(不需要写出详细代码,只需写出使用的算法策略名称、算法策略、数据准备以及程序实现流程)
解:
算法策略名贪心算法
算法策略由于需要找出去的纸币张数最小,所以需要优先找给客人大面额的纸币
数据准备
客人付的金额n
小明商品的售价m
可以退回顾客的面额用数组sz存[100,50,20,10,5,2,1]
程序实现流程:
首先计算出需要找的金额数,面额数组已经从大到小排序好,如果没排序好需要排序,所以只需遍历一遍面额数组即可,优先取出面额大的纸币找钱
时间复杂度分析:
由于面额数组已经从大到小排序好,只需遍历一遍面额数组即可,所需的时间复杂度为O(n),其中n为面额数组的长度
伪代码:
// 定义纸币面额数组 sz = [100, 50, 20, 10, 5, 2, 1] // 主程序开始 开始 // 输入总金额n和支付金额m 输入 n, m // 计算找零金额 change = n - m // 初始化纸币数量计数器 cnt = 0 // 遍历纸币面额数组 对于 i 从 0 到 6 // 计算当前面额纸币的数量 zs = change ÷ sz[i] // 从找零金额中减去当前面额纸币的总价值 change = change - (zs × sz[i]) // 累加纸币数量 cnt = cnt + zs // 如果找零金额为0,结束循环 如果 change = 0 退出循环 结束如果 结束对于 // 输出所需纸币的总数量 输出 cnt 结束