算法期末复习总结 || 分治、蛮力、回溯、分支限界、贪心、动态规划算法分析和比较

一、分治法

1. 原理

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。 求出子问题的解,就可得到原问题的解。
运用分治策略解决的问题一般来说具有以下特点:

  1. 原问题可以分解为多个子问题。这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。
  2. 原问题在分解过程中,递归地求解子问题。由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。
  3. 在求解并得到各个子问题的解后应能够采用某种方式、方法合并或构造出原问题的解。

不难发现,在分治策略中,由于子问题与原问题在结构和解法上的相似性,用分治方法解决的问题,大都采用了递归的形式。在各种排序方法中,如归并排序、堆排序、快速排序等,都存在有分治的思想。
一般步骤:

  1. 分解,将要解决的问题划分成若干规模较小的同类问题;
  2. 求解,当子问题划分得足够小时,用较简单的方法解决;
  3. 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

二、蛮力法

1. 原理

蛮力法是一种简单直接地解决问题的方法,通常直接基于问题的描述和所涉及的概念定义,找出所有可能的解。然后选择其中的一种或多种解,若该解不可行则试探下一种可能的解。

蛮力法通常用于:

  1. 搜索所有解空间:问题的解存在于规模不大的解空间中。
  2. 搜索所有的路径:这类问题中不同的路径对应不同的解。
  3. 直接计算:按照基于问题的描述和所涉及的概念定义,直接进行计算。往往是一些简单的题,不需要算法技巧的。
  4. 模拟和仿真:按照求解问题的要求直接模拟或仿真即可。

2. 其他

参考链接

三、回溯法

1. 原理

回溯法实际上一个类似穷举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”(即回退),尝试别的路径。
回溯法搜索解空间时,通常采用两种策略【剪枝策略】避免无效搜索,提高回溯的搜索效率:
约束函数 在扩展结点处剪除不满足约束的子树;
限界函数 剪去得不到问题解或最优解的子树。
归纳起来,用回溯法解题的一般步骤如下:
① 针对所给问题,确定问题的解空间树,问题的解空间树应至少包含问题的一个(最优)解。
② 确定结点的扩展搜索规则。
③ 以深度优先方式 搜索解空间树,并在搜索过程中可以采用剪枝函数来避免无效搜索。

2. 解空间

一个复杂问题的解决方案是由若干个小的决策步骤组成的决策序列,解决一个问题的所有可能的决策序列构成该问题的 解空间
解空间中满足约束条件的决策序列称为 可行解
在约束条件下使目标达到最优的可行解称为该问题的 最优解

问题的解由一个不等长或等长的解向量 X={x 1,x 2,…,x n} 组成,其中分量 x i 表示第 i 步的 操作。

问题的解空间一般用树形式来组织,也称为 解空间树状态空间
树中的每一个结点确定所求解问题的一个问题状态。树的根结点位于第 1 层,表示搜索的初始状态,第 2 层的结点表示对解向量的第一个分量做出选择后到达的状态,以此类推。
在这里插入图片描述

3. 算法框架

1. 子集树

当所给的问题是从 n 个元素的集合 S 中找出满足某种性质的子集时,相应的解空间树称为 子集树

int x[n]; //x 存放解向量,全局变量
void backtrack(int i)  //求解子集树的递归框架
{
    
     
	if(i>n) //搜索到叶子结点 输出一个可行解
		输出结果;
	else
	{
    
     
		for (j= 下界 ; 上界 ;j++) //用 j 枚举 i 所有可能的路径
		{
    
     
			x[i]=j;	//产生一个可能的解分量//其他操作
			if (constraint(i) && bound(i)
				backtrack(i+1);	//满足约束条件和限界函数 继续下一层
		}
	}
}

2. 排列树

当所给的问题是确定 n 个元素满足某种性质的排列时,相应的解空间树称为 排列树

int x[n];//x 存放解向量,并初始化
void backtrack(int i)  //求解排列树的递归框架
{
    
     
	if(i>n)		//搜索到叶子结点 输出一个可行解
		输出结果;
	else
	{
    
     
		for (j=i;j<=n;j++)		//用 j 枚举 i 所有可能的路径
		{
    
    						//第 i 层的结点选择 x[j] 的操作
			...
			swap(x[i],x[j]);	//为保证排列中每个元素不同 通过交换来实现
			if (constraint(i) && bound(i)
				backtrack(i+1);		//满足约束条件和限界函数,进入下一层
			swap(x[i],x[j]);	//恢复状态
			...				//第 i 层的结点选择 x[j] 的恢复操作
		}
	}
}

四、分支限界法

1. 原理

分支限界法类似于回溯法,是一种采用广度优先算法在问题的解空间树上进行搜索的算法。分支限界法的求解目标是:在问题的解空间上,找到符合约束条件的一个解,在某种情况下也可以称之为最优解。[分枝:就是采用广度优先策略,依次搜索活结点的所有分支。限界:设计一个限界函数,在广度搜索叶子节点时,选择一个最优的子结点作为扩展结点,以此来找到问题的最优解]

2. 队列式与优先队列式

  1. 队列式

队列式分支限界法将活结点表组成一个队列,并按照队列的先进先出原则选取下一个节点作为当前的扩展结点。

  1. 优先队列式

优先队列式分支限界法将活结点表组织成一个优先队列,并将优先队列中规定的结点优先级选取优先级最高的下一个结点作为当前扩展结点。选择优先队列式,需要将数据排成大根堆或者小根堆。

3. 限界函数设计

  1. 目标函数是求最大值:则设计上界限界函数ub(根结点的ub值通常大于或等于最优解的ub值),若si是sj的双亲结点,应满足ub(si)≥ub(sj),当找到一个可行解ub(sk)后,将所有小于ub(sk)的结点剪枝。
  2. 目标函数是求最小值:则设计下界限界函数lb(根结点的lb值一定要小于或等于最优解的lb值),若si是sj的双亲结点,应满足lb(si)≤lb(sj),当找到一个可行解lb(sk)后,将所有大于lb(sk)的结点剪枝。

五、贪心算法

1. 原理

贪心算法的基本思路是在处理问题时,主要针对当前问题的局部最优解,也就是希望不断地做出在当前看来最优的选择,达到整体的最优。

2. 求解问题应具有的性质

  1. 贪心选择性质:所求问题的整体最优解可以通过一系列的局部最优解得到
  2. 最优子结构性质:一个问题的最优解包含其子问题的最优解

3. 贪心准则

在贪心算法中,每一步上用作决策依据的选择准则被称为贪心准则。

每一次贪心选择都将所求问题简化为规模更小的子问题,并希望通过每次所做出的局部最优选择产生出一个全局最优解。

4. 哈夫曼树

由n个叶子结点可以构造出多种二叉树,其中具有最小带权路径长度的二叉树称为哈夫曼树

哈夫曼树的构造

  1. 由给定的 n 个权值 w 1 w 2 w n 构造 n 棵只有一个叶子结点的二叉树,从而得到一个二叉树的集合 F ={T1,T2…,Tn}。

  2. 在 F 中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和。即合并两棵二叉树为一棵二叉树.

  3. 重复步骤 2 ,当 F 中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。
    在这里插入图片描述

六、动态规划

1. 原理

动态规划算法通常用于求解某种具有最优性质的问题,在这类问题中,通常会有许多可行解,每一个解都对应一个值,我们希望找到最优值的解。

动态规划法与分治法类似,其基本思想也是将待求解的问题分解为若干个子问题,先求解子问题,在从这些子问题的解得到原问题的解。不同的是,适用于动态规划求解的问题,经分解得到的子问题往往不是相互独立的。

2. 所求问题具有的性质

  1. 最优性原理

如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优性原理。

  1. 无后效性

即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

  1. 有重叠子问题

即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)。

七、算法比较

1. 回溯法与蛮力法的区别

回溯法比蛮力法多了一个剪枝操作。回溯法(穷举+剪枝)是在问题的解空间树上进行深度优先搜索的算法,当没有到达叶子节点就不满足约束条件时,就回溯到上一个最近结点,选择其他路径。时间复杂度一般优于蛮力法。

2. 分支限界法与回溯法的区别

方法 解空间搜索方式 存储结点的数据结构 结点存储的特性 常用应用
回溯法 深度优先 活结点的所有可行结点被遍历后才从栈中出栈 找到满足条件的所有解
分支限界法 广度优先 队列式、优先队列式 每个结点只有一次成为活结点的机会 找到满足条件的一个解或者特定意义上的最优解

3. 贪心法与回溯法区别

贪心法是从上到下只进行深度搜索的,在问题的解空间树中,每一次在当前状态上的选择都是1,这就造成了它得出的解不一定是该问题的最优解,有可能是近似最优解[局部最优解]。

回溯法是从上到下进行深度搜索,如果深度搜索没有到达叶子节点就不满足约束条件了,就回溯到上一层结点,找到另一条岔路继续深度搜索,直到到达叶子结点,再通过广度搜索选择下一个结点。也就是说,回溯法是深度搜索和广度搜索并行的,求出的解也一定是最优解

4. 贪心法与分枝限界法区别

上面已经分析过,贪心法是只进行深度搜索的,且得到的解不一定是最优解。而分支限界法是以广度优先算法进行搜索的,求解目标是当前解空间下的一个最优解,所以得到的解也一定是最优解

5. 动态规划法与分治法的区别

动态规划算法与分治法的相同点在于,都是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
动态规划与分治法的不同点在于,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的,而分治法的子问题相互独立且与原问题性质相同。

6. 动态规划法与贪心法的区别

上面已经分析过,贪心法是只进行深度搜索的,且得到的解不一定是最优解。而动态规划法最优子结构的前提下,从状态空间树的叶子节点开始向上进行搜索,并且在每一步都根据叶子节点的当前问题的状况作出选择,从而作出最优决策,它的代价就是子问题的个数和可选择的数目,所以它求出的解一定是最优解

猜你喜欢

转载自blog.csdn.net/qq_43759081/article/details/122383139