算法设计1天津NXY.docx
《算法设计1天津NXY.docx》由会员分享,可在线阅读,更多相关《算法设计1天津NXY.docx(20页珍藏版)》请在冰豆网上搜索。
算法设计1天津NXY
NPC问题:
1:
SAT2:
最大团3:
图着色4:
哈密顿回路5:
TSP6:
顶点覆盖7:
最长路径8:
子集和
CH3:
蛮力法应用:
1:
查找问题(顺序查找、串匹配)
2:
排序问题(选择排序、起泡排序)
3:
组合问题(生成排列对象、生成子集、0/1背包、任务分配)
4:
图问题(哈密顿回路、TSP)
5:
几何问题(最近对、凸包)
CH4:
分治法应用:
(hanoi汉诺塔)
1:
排序问题(归并排序、快速排序)
2:
组合问题(最大字段和、棋盘覆盖、循环赛日程)
3:
几何问题(最近对、凸包)
CH5:
减治法
1:
查找问题(折半查找、二叉查找树)
2:
排序问题(堆排序、选择问题、)
3:
组合问题(淘汰赛冠军、假币问题)
CH6:
动态规划
1:
图问题(TSP问题、多段图最短路径)
2:
组合问题(0/1背包、最长公共子序列)
3:
查找问题(最优二叉查找树、近似串匹配)
CH7:
贪心法(霍夫曼编码)
1:
图问题(TSP问题、图着色问题、最小生成树)
2:
组合问题(背包问题、活动安排、多机调度)
CH8:
回溯法(0/1背包)
1:
图问题(图着色、哈密顿回路)
2:
组合问题(八皇后问题、批处理作业调度问题)
CH9:
分支限界
1:
图问题(TSP问题、多段图的最短路径)
2:
组合问题(任务分配、批处理作业调度)
蛮力法:
也称穷举法,是一种简单而直接地解决问题的方法,常常直接基于问题描述,也是最容易应用的方法,穷尽,无技巧。
分治法:
把大的复杂的问题分解成若干个相互独立的子问题,分别求解子问题,最后把子问题的解合并得到原问题的解。
5_减治法:
把大的问题划分成若干个子问题,只需求解其中某一个子问题,利用子问题与原问题之间的关系,得到原问题的解。
6_动态规划法:
把待求解问题分成若干个子问题,但子问题之间不是相互独立的,每个问题只需求解一次并将其解保存在一张表格中,当再次需要求解子问题时,只是简单的通过查表获得该子问题的解,避免了大量的重复性计算。
7_贪心法:
把复杂的问题分解为一系列局部最优的选择,每一步选择都是对当前解的一个扩展,知道获得问题的完整解。
8_回溯法:
有组织系统化的按深度优先搜索解空间,每次只构造可能解的一部分,然后评估这个部分解,如果该部分解可能导致完整解,对其进一步构造,否则不必构造这部分解,避免了搜索所有的可能解。
9_分支限界法:
按广度优先搜索解空间,遍历过程中对已经处理的每一个节点根据限界函数估算目标函数的可能值,选取使目标函数取得极值的节点进行广度优先搜索,不断调整搜索方向,找到问题的解。
CH_总结:
1:
查找问题:
从表的一端到另一端逐个将元素和给定值比较,相等则查找成功,否则查找失败(改进哨兵)
2:
串匹配:
给定两个串S=“s1s2…sn”和T=“t1t2…tm”,在主串S中查找子串T的过程称为串匹配,也称模式匹配
蛮力法解决串匹配(BF算法)
从主串S的第一个字符开始和模式T的第一个字符进行比较,若相等,则继续比较两者的后续字符;若不相等,则从主串S的第二个字符开始和模式T的第一个字符进行比较,重复上述过程(若失败,主串S不变,后移T)
3:
选择排序(某一趟选择某一个)
选择排序第i趟排序从第i个记录开始扫描序列,在n-i+1(1≤i≤n-1)个记录中找到关键码最小的记录,并和第i个记录交换作为有序序列的第i个记录。
4:
起泡排序
起泡排序在扫描过程中两两比较相邻记录,如果反序则交换,最终,最大记录就被“沉到”了序列的最后一个位置,第二遍扫描将第二大记录“沉到”了倒数第二个位置,重复上述操作,直到n-1 遍扫描后,整个序列就排好序了
5:
生成排列对象
假设已经生成了所有(n-1)!
个排列,可以把n插入到n-1个元素的每一种排列中的n个位置中去,来得到问题规模为n的所有排列。
按照这种方式生成的所有排列都是独一无二的,并且他们的总数应该是n(n-1)!
=n!
。
例如:
开始1
插入21221
插入3123132312213231321
6:
生成子集
n个元素的集合A={a1,a2,……,an}的所有2n个子集和长度为n的所有2n个比特串之间的一一对应关系。
建立对应关系:
为每一个子集指定一个比特串b1b2…bn,如果ai属于该子集,则bi=1;如果ai不属于该子集,则bi=0(1≤i≤n)。
例如:
比特串000001010011100101110111
子集Φ{a3}{a2}{a2,a3}{a1}{a1,a3}{a1,a2}{a1,a2,a2}
7:
0/1背包
0/1背包问题是给定n个重量为{w1,w2,…,wn}、价值为{v1,v2,…,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。
8:
任务分配
假设有n个任务需要分配给n个人执行,每人有且只有一个任务,且第j个任务分配给第i个人的成本是C[i,j](1≤i,j≤n),任务分配问题要求找出总成本最小的分配方案。
任务分配问题就是在分配成本矩阵中的每一行选取一个元素,这些元素分别属于不同的列,并且元素之和最小。
9;哈密顿回路
无向图G=(V,E),首先生成图中所有顶点的排列对象(vi1,vi2,…,vin),1:
相邻顶点之间存在边,
2:
最后一个顶点和第一个顶点之间存在边(蛮力法最坏:
时间复杂性为O(n!
))
10:
TSP问题
TSP问题是指旅行家要旅行n个城市然后回到出发城市,要求各个城市经历且仅经历一次,并要求所走的路程最短
11:
最近对
找出一个包含n个点的集合中距离最近的两个点。
蛮力法求解最近对问题的过程是:
分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑i<j的那些点对(Pi,Pj)。
12:
凸包
一个点集S的凸包是包含S的最小凸集合,其中,最小是指S的凸包一定是所有包含S的凸集合的子集,对于平面上n个点的集合S,它的凸包就是包含所有这些点(或者在内部,或者在边界上)的最小凸多边形。
(分治法)
CH4_1归并排序
二路归并排序的分治策略是:
(1)划分:
将待排序序列r1,r2,…,rn划分为两个长度相等的子序列r1,…,rn/2和rn/2+1,…,rn;
(2)求解子问题:
分别对这两个子序列进行排序,得到两个有序子序列;
(3)合并:
将这两个有序子序列合并成一个有序序列。
CH4_2快速排序
(1)划分:
选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列r1…ri-1和ri+1…rn,前一个子序列中记录的值均小于或等于轴值,后一个子序列中记录的值均大于或等于轴值;
(2)求解子问题:
分别对划分后的每一个子序列递归处理;
(3)合并:
由于对子序列r1…ri-1和ri+1…rn的排序是就地进行的,所以合并不需要执行任何操作。
CH4_3最大字段和
定由n个整数组成的序列(a1,a2,…,an),最大子段和问题要求该序列形如的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。
例如,序列(-20,11,-4,13,-5,-2)的最大子段和为:
11-4+13=20
CH4_4棋盘覆盖
分治法求解棋盘覆盖问题的技巧在于划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。
CH4_5循环赛日程
比赛日程表设计成一个n行n-1列的二维表,其中,第i行第j列表示和第i个选手在第j天比赛的选手。
(这个求解过程是自底向上的迭代过程)
CH4_6最近对
集合S分成两个子集S1和S2,每个子集中有n/2个点。
然后在每个子集中递归地求其最接近的点对,最近对可能有3中情况
CH4_7凸包
平面上n个点构成的集合S,并且这些点按照x轴坐标升序排列。
几何学中有这样一个明显的事实:
最左边的点p1和最右边的点pn一定是该集合的凸包顶点(即极点)。
设p1pn是从p1到pn的直线,这条直线把集合S分成两个子集:
S1是位于直线左侧和直线上的点构成的集合,S2是位于直线右侧和直线上的点构成的集合。
S1的凸包由下列线段构成:
以p1和pn为端点的线段构成的下边界,以及由多条线段构成的上边界,这条上边界称为上包。
类似地,S2中的多条线段构成的下边界称为下包。
整个集合S的凸包是由上包和下包构成的。
CH5_减治法思想
(1)原问题的解只存在于其中一个较小规模的子问题中;
(2)原问题的解与其中一个较小规模的解之间存在某种对应关系。
由于原问题的解与较小规模的子问题的解之间存在这种关系,所以,只需求解其中一个较小规模的子问题就可以得到原问题的解。
一般是O(log2n)数量级
CH5_1折半查找
在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键码相等,则查找成功;若给定值小于中间记录的关键码,则在中间记录的左半区继续查找;若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。
不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。
CH5_2二叉查找树
具有n个结点的判定数的深度为
由二叉排序树的定义,在二叉排序树root中查找给定值k的过程是:
⑴若root是空树,则查找失败;
⑵若k=根结点的值,则查找成功;
⑶否则,若k<根结点的值,则在root的左子树上查找;
⑷否则,在root的右子树上查找;
CH5_3堆排序
首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录,然后将它从堆中移走(通常将堆顶记录和堆中最后一个记录交换),并将剩余的记录再调整成堆,这样又找出了次大的记录,以此类推,直到堆中只有一个记录为止。
CH5_4选择问题
一般情况下,设待划分的序列为ri~rj,选定一个轴值将序列ri~rj进行划分,使得比轴值小的元素都位于轴值的左侧,比轴值大的元素都位于轴值的右侧,假定轴值的最终位置是s,
CH5_5淘汰赛冠军
假设有n=2k个选手进行竞技淘汰赛,最后决出冠军的选手,用函数
boolComp(stringmem1,stringmem2);
模拟两位选手的比赛,若mem1获胜则函数Comp返回TRUE,否则函数Comp返回FALSE
CH5_6假币问题
在n枚外观相同的硬币中,有一枚是假币,并且已知假币较轻。
可以通过一架天平来任意比较两组硬币,从而得知两组硬币的重量是否相同,或者哪一组更轻一些,但不知道轻多少,假币问题是要求设计一个高效的算法来检测出这枚假币。
(3,3,2分组)
CH6:
动态规划
动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。
用动态规划法求解的问题具有特征:
✓能够分解为相互重叠的若干子问题;
✓满足最优性原理(也称最优子结构性质):
该问题的最优解中也包含着其子问题的最优解。
动态规划一般步骤
(1)分段:
将原问题分解为若干个相互重叠的子问题;
(2)分析:
分析问题是否满足最优性原理,找出动态规划函数的递推式;
(3)求解:
利用递推式自底向上计算,实现动态规划过程。
CH6_1TSP问题
TSP问题是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。
CH6_2多段图最短路径
多段图的最短路径问题是求从源点到终点的最小代价路径。
CH6_30/1背包
CH6_4最长公共子序列
给定两个序列X和Y,当另一个序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
最长公共子序列问题就是在序列X和Y的公共子序列中查找长度最长的公共子序列。
CH6_5最优二叉查找树
CH6_6近似串匹配
CH7:
贪心法(霍夫曼编码)
贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。
换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优,这种局部最优选择并不总能获得整体最优解,但通常能获得近似最优解。
例如_1:
贪心法求解付款问题。
贪心法求解的问题的特征:
(1)最优子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质,也称此问题满足最优性原理。
(2)贪心选择性质
所谓贪心选择性质是指问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来得到。
候选集合C:
各种面值的货币构成候选集合。
解集合S:
已付出的货币构成解集合
解决函数:
检查解集合S是否构成问题的完整解。
解决函数是已付出的货币金额恰好等于应付款。
选择函数:
即贪心策略,这是贪心法的关键,它指出哪个候选对象最有希望构成问题的解,选择函数通常和目标函数有关。
贪心策略就是在候选集合中选择面值最大的货币。
可行函数:
检查解集合中加入一个候选对象是否可行,即解集合扩展后是否满足约束条件。
例如,在付款问题中,可行函数是每一步选择的货币和已付出的货币相加不超过应付款。
CH7_1:
贪心法_TSP问题
最近邻点策略:
从任意城市出发,每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。
最短链接策略:
每次在整个图的范围内选择最短边加入到解集合中,但是,要保证加入解集合中的边最终形成一个哈密顿回路。
因此,当从剩余边集E'中选择一条边(u,v)加入解集合S中,应满足以下条件:
2边(u,v)是边集E'中代价最小的边;最短
②边(u,v)加入解集合S后,S中不产生回路;无回路
3边(u,v)加入解集合S后,S中不产生分枝;无分支
CH7_2:
贪心法_图着色问题
选择一种颜色,以任意顶点作为开始顶点,依次考察图中的未被着色的每个顶点,如果一个顶点可以用颜色1着色,换言之,该顶点的邻接点都还未被着色,则用颜色1为该顶点着色,当没有顶点能以这种颜色着色时,选择颜色2和一个未被着色的顶点作为开始顶点,用第二种颜色为尽可能多的顶点着色,如果还有未着色的顶点,则选取颜色3并为尽可能多的顶点着色,依此类推。
双向图:
2n个顶点的无向图,顶点的编号从1到2n,当i是奇数时,顶点i与除了顶点i+1之外的其他所有编号为偶数的顶点邻接,当i是偶数时,顶点i与除了顶点i-1之外的其他所有编号为奇数的顶点邻接
CH7_3:
贪心法_最小生成树
设G=(V,E)是一个无向连通网,生成树上各边的权值之和称为该生成树的代价,在G的所有生成树中,代价最小的生成树称为最小生成树
最小生成树两种可选策略:
最近顶点策略:
Prim任选一个顶点,并以此建立起生成树,每一步的贪心选择是简单地把不在生成树中的最近顶点添加到生成树中。
最短边策略:
Kruskal设G=(V,E)是一个无向连通网,令T=(U,TE)是G的最小生成树。
最短边策略从TE={}开始,每一次贪心选择都是在边集E中选取最短边(u,v),如果边(u,v)加入集合TE中不产生回路,则将边(u,v)加入边集TE中,并将它在集合E中删去。
CH7_4:
贪心法_背包问题
至少有三种看似合理的贪心策略:
选择价值最大的物品,因为这可以尽可能快地增加背包的总价值。
但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗得太快,使得装入背包的物品个数减少,从而不能保证目标函数达到最大。
选择重量最轻的物品,因为这可以装入尽可能多的物品,从而增加背包的总价值。
但是,虽然每一步选择使背包的容量消耗得慢了,但背包的价值却没能保证迅速增长,从而不能保证目标函数达到最大。
选择单位重量价值最大的物品,在背包价值增长和背包容量消耗两者之间寻找平衡。
CH7_5:
贪心法_活动安排
贪心法求解活动安排问题的关键是如何选择贪心策略,使得按照一定的顺序选择相容活动,并能安排尽量多的活动。
至少有两种看似合理的贪心策略:
(1)最早开始时间:
这样可以增大资源的利用率。
(2)最早结束时间:
这样可以使下一个活动尽早开始。
CH7_6:
贪心法_多机调度
贪心法求解多机调度问题的贪心策略是
最长处理时间作业优先,即把处理时间最长的作业分配给最先空闲的机器,这样可以保证处理时间长的作业优先处理,从而在整体上获得尽可能短的处理时间。
CH8:
回溯法(0/1背包)
0/1背包问题,其可能解的表示方式可以有以下两种:
{(),
(1),
(2),(3),(1,2),(1,3),(2,3),(1,2,3)}
可能解由一个不等长向量组成,当物品i(1≤i≤n)装入背包时,解向量中包含分量i,否则,解向量中不包含分量i,当n=3时
{(0,0,0),(0,0,1),(0,1,0),(1,0,0),(0,1,1),(1,0,1),(1,1,0),(1,1,1)}
可能解由一个等长向量{x1,x2,…,xn}组成,其中xi=1(1≤i≤n)表示物品i装入背包,xi=0表示物品i没有装入背包,当n=3时
所有可能的解向量构成了问题的解空间。
解空间树:
树的根结点位于第1层,表示搜索的初始状态,第2层的结点表示对解向量的第一个分量做出选择后到达的状态,第1层到第2层的边上标出对第一个分量选择的结果,依此类推,从树的根结点到叶子结点的路径就构成了解空间的一个可能解。
剪枝:
判断某个结点是否包含问题的(最优)解,如果肯定不包含,则跳过对以该结点为根的子树的搜索
剪枝函数:
(1)用约束条件剪去得不到可行解的子树;
(2)用目标函数剪去得不到最优解的子树。
回溯发典型的解空间树:
子集树:
当所给问题是从n个元素的集合中找出满足某种性质的子集时,相应的解空间树称为子集树。
在子集树中,|S1|=|S2|=…=|Sn|=c,即每个结点有相同数目的子树,通常情况下c=2,所以,子集树中共有2n个叶子结点,因此,遍历子集树需要Ω(2n)时间。
排列树:
当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。
在排列树中,通常情况下,|S1|=n,|S2|=n-1,…,|Sn|=1,所以,排列树中共有n!
个叶子结点,因此,遍历排列树需要Ω(n!
)时间。
CH8_1:
回溯法_图着色
回溯法求解图着色问题,首先把所有顶点的颜色初始化为0,然后依次为每个顶点着色。
在图着色问题的解空间树中,如果从根结点到当前结点对应一个部分解,也就是所有的颜色指派都没有冲突,则在当前结点处选择第一棵子树继续搜索,也就是为下一个顶点着颜色1,否则,对当前子树的兄弟子树继续搜索,也就是为当前顶点着下一个颜色,如果所有m种颜色都已尝试过并且都发生冲突,则回溯到当前结点的父结点处,上一个顶点的颜色被改变,
CH8_2:
回溯法_哈密顿回路
CH8_3:
回溯法_八皇后问题
四皇后问题的解空间树是一个完全4叉树,树的根结点表示搜索的初始状态,从根结点到第2层结点对应皇后1在棋盘中第1行的可能摆放位置,从第2层结点到第3层结点对应皇后2在棋盘中第2行的可能摆放位置
CH8_4:
回溯法_批处理作业调度问题
批处理作业的一个最优调度应使机器1没有空闲时间,且机器2的空闲时间最小。
可以证明,存在一个最优作业调度使得在机器1和机器2上作业以相同次序完成。
六个方案中的第一种:
CH9:
分支限界
分支限界法首先确定一个合理的限界函数,并根据限界函数确定目标函数的界[down,up]。
然后,按照广度优先策略遍历问题的解空间树,在分支结点上,依次搜索该结点的所有孩子结点,分别估算这些孩子结点的目标函数的可能取值,如果某孩子结点的目标函数可能取得的值超出目标函数的界,则将其丢弃,因为从这个结点生成的解不会比目前已经得到的解更好;否则,将其加入待处理结点表(以下简称表PT)中。
依次从表PT中选取使目标函数的值取得极值的结点成为当前扩展结点,重复上述过程,直到找到最优解。
随着这个遍历过程的不断深入,表PT中所估算的目标函数的界越来越接近问题的最优解。
当搜索到一个叶子结点时,如果该结点的目标函数值是表PT中的极值(对于最小化问题,是极小值;对于最大化问题,是极大值),则该叶子结点对应的解就是问题的最优解;否则,根据这个叶子结点调整目标函数的界(对于最小化问题,调整上界;对于最大化问题,调整下界),依次考察表PT中的结点,将超出目标函数界的结点丢弃,然后从表PT中选取使目标函数取得极值的结点继续进行扩展。
分支限界法的一般过程:
1.根据限界函数确定目标函数的界[down,up];
2.将待处理结点表PT初始化为空;
3.对根结点的每个孩子结点x执行下列操作
3.1估算结点x的目标函数值value;
3.2若(value>=down),则将结点x加入表PT中;
4.循环直到某个叶子结点的目标函数值在表PT中最大
4.1i=表PT中值最大的结点;
4.2对结点i的每个孩子结点x执行下列操作
4.2.1估算结点x的目标函数值value;
4.2.2若(value>=down),则将结点x加入表PT中;
4.2.3若(结点x是叶子结点且结点x的value值在表PT中最大),
则将结点x对应的解输出,算法结束;
4.2.4若(结点x是叶子结点但结点x的value值在表PT中不是最大),
则令down=value,并且将表PT中所有小于value的结点删除;
注意:
分支限界法对问题的解空间树中结点的处理是跳跃式的,回溯也不是单纯地沿着双亲结点一层一层向上回溯
分支限界法的时间性能
分支限界法和回溯法实际上都属于蛮力穷举法,当然不能指望它有很好的最坏时间复杂性,遍历具有指数阶个结点的解空间树,在最坏情况下,时间复杂性肯定为指数阶。
与回溯法不同的是,分支限界法首先扩展解空间树中的上层结点,并采用限界函数,有利于实行大范围剪枝,同时,根据限界函数不断调整搜索方向,选择最有可能取得最优解的子树优先进行搜索。
所以,如果选择了结点的合理扩展顺序以及设计了一个好的限界函数,分支界限法可以快速得到问题的解。
分支限界法的缺点
首先,一个更好的限界函数通常需要花费更多的时间计算相应的目标函数值
其次,由于分支限界法对解空间树中结点的处理是跳跃式的,算法稍微复杂
再次,算法要维护一个待处理结点表PT,需要较大存储空间,分支限界法需要的空间复杂性是指数阶。
CH9_1:
分支限界_TSP问题
上界:
贪心法求得近似解为1→3→5→4→2→1,其路径长度为1+2+3+7+3=16,这可以作为TSP问题的上界。
下界:
如果把矩阵中每一行最小的两个元素相加再除以2,如果图中所有的代价都是整数,再对这个结果向上取整,就得到了一个合理的下界。
目标函数的界[14,16]。
需要强调的是,这个解并不是一个合法的选择(可能没有构成哈密顿回路),它仅仅给出了一个参考下界。
CH9_2:
分支限界_多段图的最短路径
设图G=(V,E)是一个带权有向连通图,如果把顶点集合V划分成k个互不相交的子集Vi(2≤k≤n,1≤i≤k),使得E中的任何一条边(u,v),必有u∈Vi,v∈Vi+m(1≤i<k,1<i+m≤k),则称图G为多段图,