穷举VS暴搜VS深搜VS回溯VS剪枝

什么是回溯算法?

回溯算法是一种经典的递归算法,通常用于结合组合问题、排列问题和搜索问题等。

回溯算法的基本思想:从一个初始状态开始,按照一定的规则向前搜索,当搜索到某个状态无法前进时,回退到前一个状态,再按照其他的搜索规则。回溯算法再搜索过程中维护一个状态树,通过遍历状态树来实现对所有可能解的搜索。

回溯算法的核心思想:“试错”,即再搜索的过程中不断地做出选择,如果选择正确,则继续向前搜索;否则,回退到上一个状态,重新做出选择。回溯算法通常用于解决具有多个解,且每个解都需要搜索才能找到的问题。

回溯算法的模板(不过最好自己多写写,也能总结出来):


	void backtrack(vector<int>& path, vector<int>& choice, ...) { 	// 满足结束条件
		if (/* 满足结束条件 */) {
					// 将路径添加到结果集中
			 res.push_back(path); 
					return;
        }
		// 遍历所有选择	
		for (int i = 0; i < choices.size(); i++) {
		// 做出选择
		 path.push_back(choices[i]);
		// 做出当前选择后继续搜索
		backtrack(path, choices);
		// 撤销选择
		 path.pop_back();
	}
}

其中,path表示当前已经做出的选择,choices表示当前可以做的选择。再回溯算法中,我们需要做出选择,然后递归地调用回溯函数。如果满足结束条件,则将当前路径添加到结果集中;否则,我们需要撤销选择,回到上一个状态,然后继续搜索其他的选项。

回溯算法的时间复杂度通常较高。因为它需要遍历所有可能的解。但是回溯算法的空间复杂度较低,因为只需要维护一个状态树。在实际应用中,回溯算法通常需要通过剪枝等方法进行优化,以减少搜索的次数,从而提高算法的效率。

回溯算法的应用:

组合问题:

组合问题是指从给定的一组数(不重复)中选取出所有可能的k个数的组合。例如,给定数集[1,2,3],要求选取k=2个数的所有组合。

排列问题
排列问题是指从给定的一组数(不重复)中选取出所有可能的 k 个数的排列。例如,给定数集 [1,2,3],要求选取 k=2 个数的所有排列。​

子集问题
子集问题是指从给定的一组数中选取出所有可能的子集,其中每个子集中的元素可以按照任意顺序排列。例如,给定数集 [1,2,3],要求选取所有可能的子集。​

总结:

回溯算法是一种非常重要的算法,可以解决许多组合问题、排列问题和搜索问题等。回溯算法的核心思想是搜索状态树,通过遍历状态树来实现对所有可能解的搜索。回溯算法的模板非常简单,但是实现起来需要注意一些细节,比如如何做出选择、如何撤销选择等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值