深搜之回溯法总结

回溯法是个好东西, 当自己对一个问题没有任何思路的时候就可以用回溯法, 虽然效率是一个严重的问题, 但是却能给问题一个形象的解释, 或者可以从回溯法想到一个不错的算法也不一定


当遇到一个可以用到回溯法的时候需要按照如下步骤进行:

1. 确定问题的一个解空间树, 这个解空间树至少包含一个你需要的那个解, 否则这个树就完全没有意义了

2. 组织好这棵树, 弄明白这棵树的每一个节点代表什么, 每一个分支代表什么

3. 从这棵树的根节点不断的向下深搜, 当遇到不合适的节点的时候直接跳过以这个节点为根的子树

4. 当搜索到了叶子节点的时候就回溯

5. 不断的重复这个3, 4步骤

附加: 根据具体的问题可以定义限界条件, 最优值条件, 根据这两个条件可以剪枝了


事例一: 写出一个数1 - n 的全排列(排列数)


这棵树就是一颗排列树, 第 i 层就是第 i 个数排列数的可能性

第 i 层的每一个节点就是第 i 个排列数的 可能性

分支就是下一个排列数

得到的解:X = [x1, x2, x3, x4, .... xn] 就是解序列,X2 代表 第2 个排列数是x2;  这其中的X可能就有我们想要的X, 那么这个X序列就是解了


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int MaxE = 1003, MaxV = 1003;
int n;
bool vis[MaxV];   // 纪录点在本次排列中被使用过
int tmp[MaxV];    //存中见结果
void backtrack(int cur)   //cur表示当前层, 就是第cur个排列数的标号
{
	if(cur > n)     //如果层数到了叶子节点
	{
		for(int i = 1; i <= n; i++)
			cout << tmp[i] << " ";
		cout << endl;
		return ;

	}
	for(int i = 1; i <= n; i++)  //找当前层合适的数作为第cur个排列数
	{
		if(vis[i] == false)
		{
			vis[i] = true;       //标记 i 被使用过了
			tmp[cur] = i;        //纪录当前层的排列数
			backtrack(cur + 1);  //找
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值