算法应用:共40分,2个小题,每小题20分分析题:共20分,2个小题,每小题10分算法设计:共20分,1个小题,每小题20分综合题:共20分,1个小题,每小题20分 (1)掌握蛮力法算法思想和实现思路。
蛮力法算法思想又称为枚举法、穷举法、暴力法,是指采用遍历技术整个解空间,即采用一定的策略将待求解问题的所有元素依次处理一次,从而找出问题的解。
实现思路:根据问题中的条件将可能的情况列举出来,逐一尝试从中找出满足问题条件的解。
设计思路:1、找出枚举范围2、找出约束条件
看的别人的博客和书上的定义:算法分析学习笔记二 蛮力法 (2)求解幂集问题,给定一个包含n个元素的集合,实现求解幂集的函数。
大脑已经不思考了,白嫖真香,将大佬的代码蛮力法求解幂集问题改了一下,不想自己写了。 (3)求解全排列问题,给定n个互不相同的元素,实现求解全排列的函数。
这题用递归做的,将集合中的元素从头开始交换,也是蛮力法,形式上好看一点。
算法思路参考 【算法设计与分析】分治法与最近点对问题
1、求解最长公共子序列问题。要求要有结果展示。
这个也是书上有的经典问题,使用动态规划的思想。
状态转换方程:
https://blog.csdn.net/weixin_44279771/article/details/105989975
n皇后问题书上有原题,这是一个非常经典的问题,要记住状态转换方程;
递归模型为:
第二章 递归算法设计
第三章 分治法
第四章 蛮力法
第七章 贪心法
第八章 动态规划 递归算法:递归算法是执行过程和结果
算法设计应用递归算法
使用递归算法就是将原问题不断分解为规模缩小的子问题,然后递归调用方法来表示问题的解。
求解步骤: 明确函数要做什么明确递归的结束条件找出函数的等价关系式
最好写出递归方程。 递推法和倒推法:猴子吃桃等简单问题及类似问题的灵活运用
悟空第一天摘下桃子若干,当即吃掉一半,还不过瘾,又多吃一个,第二天又将剩下的桃子吃掉一半多一个,以后每天吃掉前一天剩下的一半多一个,到第n天准备吃的时候只剩下一个桃子。聪明的你,请帮悟空算一下,他第一天开始吃的时候桃子一共有多少个呢?
贪心法
贪心法是寻找最优解的常用方法,将求解过程分成若干个步骤,每个步骤都应用贪心原则,选取当前状态下最好/最优的选择。
可能出现的经典问题:找零钱、
活动安排问题、
多机调度问题、
田忌赛马问题、
程序存储问题、
汽车加油问题、
流水作业调度问题
以及类似问题等
找零钱:从大到小排序,先选最大的
活动安排问题:安排尽可能多的活动就是要按结束时间从小到大排序,先挑小的兼容
多机调度问题:让最长处理时间的作业优先分配给最先空闲的机器
田忌赛马问题:下面有详解
程序存储问题:先存最小的
汽车加油问题:能到下一站就不加油,不让就在这一站加满
流水作业调度问题:分为两组,第一组为第一生产线时间小于第二生产线的作业,按第一生产线的时间从小到大排序,小的先执行;第二组为第一生产线时间大于第二生产线的作业,按第二生成线的时间从大到小排序,大的先执行
求解思路:都是贪心法取局部最优解,例如田忌赛马的问题,就是递减排序,从当前最大开始能匹配就用,不能就使用当前最小的匹配 分治法
应用分治法求解的时候有一个非常明显的特征:这个问题的规模可以分解为多个规模较小的子问题。这个看起来也是动态规划的要求,但是动态规划算法是用来求解最优解的问题,分治法是用于求解一个较大规模的解。
分治法一般可以用递归算法实现,分治法是一种求解问题的策略,而递归是一种实现求解算法的技术。
可能出现的经典问题:
求第n小元素值、
求中位数、
同时求最大最小值、
棋盘覆盖问题、
Strassen矩阵乘法(详解矩阵乘法中的Strassen算法)等
求解第k小元素:类似于快速排序的思路,递归出口为a[i]==k-1,如果k-1i,就在右区间找。
求中位数:两个序列的中位数比较,然后分别减半找另外一边,当只有两个元素时小的就是中位数。
同时求最大最小值:不断二分,只剩两个的时候比较大小并记录一个临时值,最后和全局值比较更新
棋盘覆盖问题:棋盘问题解析(这个问题放到现在应该不难理解了)
求解思路:运用递归算法的技术,确定递归出口和递归条件。 动态规划
可能出现的经典问题:
多段图问题:分阶段选出最短路径、
资源分配问题:先只分配一个厂,然后在其基础上加其他厂、
矩阵连乘问题https://blog.csdn.net/qq_19782019/article/details/94356886
最大子段和、
最长递增子序列、
编辑距离、
最长公共子串等
最大子段和的状态转换方程:
编辑距离问题的状态转换方程:
求解思路:需要用到上个阶段结果的问题就使用dp[][]数组存放;不需要用到上个阶段结果的问题就使用len[]数组存放(例如最长递增子序列问题) 图搜索算法
可能出现的经典问题:
排列树与子集树上的回溯、
算法的剪枝与限界分支算法、
简单问题的分支与限界求解
0-1背包问题的多种方法求解
图搜索问题应该会和分支限界算法一起考,在广度优先遍历的基础上加上剪枝和限界函数。 概率算法
可能出现的经典问题:
蒙特卡罗算法求解数值计算问题(频率在测试实例充分多时近似为概率)、
舍伍德策略对算法性能的影响(可以用来消除算法的时间复杂性与输入实例间的联系)
蒙特卡罗算法最经典的就是用于求解PI的近似值,通过随机密度求解区域分配,进而算出PI的近似值。
舍伍德概率算法是在一次计算之前根据随机数将待计算序列中随机确定一个元素作为基准,并将它与第一个元素交换,则计算之后的子序列更加趋近于期望,从而使算法的行为不受待计算序列的不同输入实例的影响。(在确定性算法中引入随机性,使计算时间复杂性对所有实例而言相对均匀) 分析题部分
试题形式包括计算推导、算法模型中结论和定理的分析与证明
可能考的内容:
算法的性能指标:
算法性能定理与结论的论证、
部分算法模型结论的证明
递归算法:一般难度非递归与递归算法的时间空间性能的推算。 算法设计部分-蛮力法
考一些编码量不大的枚举问题求解、不太复杂的递归算法设计。
蛮力法就是找出全部的解空间,然后顺序遍历整个解空间寻找可行解,也可以用一个全局变量记录,找最优解。 demo:求解与k无关的数
demo1(动态规划,轮流拿牌问题)
1.桌子上摆放着144 张麻将牌,两个人轮流取牌,每人每次最少取走1张,最多取走4 张,谁拿到最后一张麻将牌谁输,设先取牌者为A,后取牌者为B,如果双方均完全理智,没有任何失误∶
(1)请详细说明先取牌者获胜的策略;(5分)
(2)将问题推广为任意的 n张麻将牌,两个人轮流取牌,每人每次最少取走 1 张,最多取走k 张,请详细说明此时先拿牌者取胜的策略。(5分) 解
(1)从桌子上只剩1张麻将牌开始倒推剩7张麻将牌即可知:只要在取牌让剩余牌数还剩余6张时,然后B再取,A永远取5-nB 张就能将最后一张牌留给B。
(2)先计算m=n MOD(k+1),如果m!=1,先取m-1张(取牌让剩余牌正好位k+2张),接下来永远取(k+1)-nB 张就能将最后一张牌留给B,先取者必胜
(如果m为1,则先取者无论取多少张,B就可以用同样的策略,永远取(k+1)-nA 来进行,则先取者必败) demo2(贪心法,田忌赛马问题)
2.田忌赛马是中国历史上有名的博弈故事。如果田忌和齐威王比赛的马由3匹变成了n 匹(n>3),齐威王的策略不变,仍然让他的马按从优到劣的顺序出赛,田忌则可以按任意顺序选择他的马出赛。赢一局,田忌可以得到100 两银子,输一局,田忌就要输掉100 两银子。已知齐威王和田忌的所有马的奔跑速度都不相同,并且已对两人的马按速度分别从快到慢排好序,请设计一个算法,帮助田忌赢得最多的银子。
(1)描述求解该问题的算法策略和解题步骤;
(2)现已知齐威王和田忌各有11 匹马,两队马的速度如下表,请简要说明算法执行的全过程。 马的编号1234567891011齐威王6891215202930343536田忌57101416171823253233
(3)算法执行后,田忌的盈利是多少? 解
(1)采用贪心的算法策略;
面对齐威王顺序出场的各匹马,如果田忌当前最快的马的速度更快就派最快的马出场;否则派最慢的马出场迎战齐威王当前最快的马
(2)算法执行过程如下:
33<36,田忌派速度为5的马出战齐威王速度36的马,败;
33<35,田忌派速度为7的马出战齐威王速度35的马,败;
33<34,田忌派速度为10的马出战齐威王速度34的马,败;
33>30,田忌派速度为33的马出战齐威王速度30的马,胜;
32>29,田忌派速度为32的马出战齐威王速度29的马,胜;
25>20,田忌派速度为25的马出战齐威王速度20的马,胜;
23>15,田忌派速度为23的马出战齐威王速度15的马,胜;
18>12,田忌派速度为18的马出战齐威王速度12的马,胜;
17>9,田忌派速度为17的马出战齐威王速度9的马,胜;
16>8,田忌派速度为16的马出战齐威王速度36的马,胜;
14<6,田忌派速度为14的马出战齐威王速度36的马,胜;
最终结果为胜8局,负3局。
(3)田忌的盈利为100*(8-3)=500两银子。 练习题(动态规划,最长递增子串问题)
3.对于给定的一个序列{a1,a2,a3,… an},存在一子序列{ai1, ai2,a3,…,ain},满足ai 例如∶对于序列{1,7,3,5,9,4,8},子序列{1,7},{3,4,8}等为其上升子序列,子序列{1,3.5.8}为最长上升子序列,长度是4。 对于给定的序列,要求以尽可能快的方式求出最长上升子序列及其长度。 (1)描述求解该问题的算法策略和解题步骤; (2)对序列{8,5,2,3,7,4,1,9,6,8,9},求最长上升子序列及长度。
练习题(分治法,求中位数)
4.一个长度为n 的递增有序序列a【0…n-1】,处于中间位置的元素称为a 的中位数,两个有序序列的中位数是包含两者所有元素的有序序列的中位数。为简化问题,含有n个元素的有序序列a【s…t】,仅考虑下标为m=处的元素为中位数。例如∶ 序列a=(11,13,15,17,19),中位数是15;序列b=(2,4,6,8,20),中位数是6;a、b 两个有序序列合并起来的中位数为11。 (1)设计一个效率较高的算法求给定的两个等长有序序列的中位数,说明求解该问题的算法策略和解题步骤; (2)对于如下两个有序序列,写出求解中位数的全过程。(4分) a=(346142778 96),b=(1928476163 73 85)
练习题(分支限界法,0/1背包问题)
5.有n个重量分别为{w;w2.…,wn}的物品,它们的价值分别为{v1,v2,…,v},给定一个容量为W的背包,从这n个物品中选取一些物品放入该背包,每个物品要么选中要么不选中,要求选中的物品能够放入背包,装入的重量和恰好为W,而且具有最大的价值。 (1)设计用回溯法求解该问题的左剪枝条件与右剪枝的限界条件; (2)设 W=7,对如下4 件物品,画出用回溯法进行剪枝和限界时,求解该问题的完整解空间树,并说明最优解的解向量。
编号1234重量5423价值1215810
题1
(1)利用动态规划的思想,用递推法从头开始递推, 状态转换方程为 初态:len[i]=1,0<=i<=n-1,len表示序列长度 递推式:len[i]=max(len[i],len[j]+1) 用辅助数组存放前驱坐标方便结果输出
(2)对序列{8,5,2,3,7,4,1,9,6,8,9}的计算过程如下:
序列下标012345678910元素值85237419689序列长度11123314456前驱下标-1-1-1233-14589
因此最长上升子序列为(2,3,4,6,8,9),长度为6.
题2
(1) 采用分治法的二分法求解,算法为: 由题n=1,a,b中唯一元素的较小者为中位数 否则,分别求出a,b的中位数ma 和mb 1、如果ma =mb ,则就为中位数,算法结束 2、如果 ma 否则ma >mb ,舍弃a的后半部分和b的前半部分 (2)求解过程: 画表表达更加清晰:
数组ab初始状态3,4,6,14,27,78,9619,28,47,61,63,73,85第一次二分后14,27,78,9619,28,47,61第二次二分后78,9619,28第三次二分后7828
最后即得中位数为28.
题3
(1)设Tw 表示已经装入背包的物品总重量,Tv 背包中物品的总价值; 左剪枝条件: 对于第i层的结点,如果Tw +w[i]已超过W,就不能再选择w[i] 右限界条件: 设剩余物品重量Rw=w[i]+w[i+1]+…+w[n] 当不选择物品i时:Rw-w[i]=w[i+1]+…+w[n] 如果Tw +Rw -w[i] (2)回溯法加剪枝和限界的完整解空间树: 画解空间树可知:可行解2个,最优解是25,解向量为{0,1,0,1}。
题1(分析题)
设下列算法中的n为充分大是正整数: (1)详细计算说明算法中的子语句执行的次数多少次? (2) 哪个符号更合适表示该算法的时间复杂度? (3)算法的时间复杂度是多少?
解: (1) (2)用 更合适;因为该语句的执行次数与输入数据的分布无关,只与输入数据的大小n有关。 (3)算法的时间复杂度为,因为当n充分大时,,即时间复杂度既是频度的上界,也是频度的下界。
题2(分析题)
解:(1)全局变量x-输出3125,因为当递归到达出口后,回退时永远是x最后输入的值:1 * 5 * 5 *5 * 5 * 5; (2)局部变量x-输出1680,因为当递归到达出口后,回退时会还原x在进入该层递归时输入的值:1 * 5 * 3 * 8 * 2 * 7; (3)可以直接转换;因为该算法是尾递归,直接将继续递归的条件变为循环条件,从递归出口向递归入口倒推。
题3(贪心法,田忌赛马问题的类似问题)
和田忌赛马问题一致,利用贪心法求解,先排序,然后递推即可。
题4(动态规划,设备分配问题)
这题有多个阶段,应该使用动态规划的策略; 该问题有局部最优性特点,而且下一阶段的决策不影响上以阶段的决策。 dp数组:
01234567000000000A0124881113B0246781315C03579111316
状态转换方程: 设原数组名为sum[3][7]
问题描述; 给你一系列的矩阵A1,A2,A3,…,An和一系列的整数P0,P1,P2…,Pn,每个矩阵 Ai 的规模为Pi-1 * Pi。 现在,请你计算这些矩阵连乘所需要的最少的计算次数是多少?
解:
找出最优子结构,在本问题中,即找出如何划分“括号”的方法。找出最优子结构的递推式。 定义的值为计算Ai 所需要的最小的计算次数, Ai…k的乘积结果为一个规模为Pi-1 * Pk的矩阵, 而Ak+1…Aj的乘积结果为一个规模为Pk * Pj的矩阵,所以,求Ai…j的最少乘积次数则为【Ai…k所需要的最少乘积次数】+【Ai+1…j所需要的最少乘积次数】+【中间生成的两个临时矩阵所需要的乘积次数】。 将K的可能值都代进去试一遍,K的可能值只有j-i种,找出m[i,j]最小的那一个情况,此时的K值就是我们需要的,并且最小乘积次数也找到了,就是m[i,j]次。
对于这类的具体问题可以采用自底向下的方式去计算最优值,将这个连乘问题拆分成两个矩阵相乘的问题,然后找出最佳的乘法分配;计算时都需要先将m[i][k]和m[k+1][j]求出来,递归到最下层只有两个矩阵相乘的时候,递增序列就求出来了。