前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【精选】算法设计与分析(第五章回溯法)

【精选】算法设计与分析(第五章回溯法)

作者头像
命运之光
发布2024-03-20 13:54:30
1600
发布2024-03-20 13:54:30
举报
文章被收录于专栏:我在本科期间写的文章

前言

总结算法设计与分析课程期末必记知识点。

第五章回溯法
1、回溯法概念

回溯法实际上是一个类似穷举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时就“回溯”,尝试其他路径,所以回溯法有“通用的解题法”之称。

2、回溯法可以求解的问题有哪些

可行解最优解

3、回溯法算法设计的三个点

(1)结点是如何扩展的。 (2)在解空间树中按什么方式搜索,一种是采用深度优先遍历(DFS),回溯法就是这种方式;另一种是采用广度优先遍历(BFS),下一章介绍的分支限界法就是这种方式。 (3)解空间树通常是十分庞大的,如何高效地找到问题的解。

4、回溯法解空间树的两种类型(重点简答)

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

5、什么是活结点,什么是扩展结点,什么是死结点

活结点:指自身已生成但其孩子结点没有全部生成的结点 扩展结点:指正在产生孩子结点的结点 死结点:指其所有子结点均已产生的结点

6、回溯法搜索解空间时通常采用的两种策略

一是:约束函数 二是:限界函数 这两类统称为剪枝函数

7、回溯法求解步骤

(1)针对给定的问题确定问题的解空间树,问题的解空间树应至少包含问题的一个解或者最优解。 (2)确定结点的扩展搜索规则。 (3)以深度优先方式搜索解空间树,并在搜索过程中可以采用剪枝函数来避免无效搜索。其中,深度优先方式可以选择递归回溯或者迭代(非递归)回溯。

8、回溯法与深度优先遍历的异同(简答)

相同点

  • 回溯法在实现上也是遵循深度优先的。

不同的

  • 访问次序不同
  • 访问次数不同
  • 剪枝不同
9、 回溯法=DFS+剪枝

在通常情况下,回溯法的效率会高于蛮力法

10、解空间树为子集树和排列树的时间复杂度

子集树的时间复杂度为:

O(2^n)
O(2^n)

排列树的时间复杂度为:

O(n!)
O(n!)
11、 求解0/1背包问题(重点)

第一种

代码语言:javascript
复制
void dfs(int i, int tw, int tv, int rw, int op[])//求解0/1背包问题
{
	if (i > n)				//找到一个叶子结点
	{
		if (tw == W && tv > maxv)	//找到一个满足条件的更优解,保存它
		{
			maxv = tv;
			for (int j = 1; j <= n; j++)	//复制最优解
				x[j] = op[j];
		}
	}
	else                    //尚未找完所有物品
	{
		if (tw + w[i] < W)		//左孩子结点剪枝
		{
			op[i] = 1;			//选取第i个物品
			dfs(i + 1, tw + w[i], tv + v[i], rw - w[i], op);
		}
		if (tw + rw - w[i] >= W)		//右孩子结点剪枝
		{
			op[i] = 0;					//不选取第i个物品,回溯
			dfs(i + 1, tw, tv, rw - w[i], op);
		}
	}
}

第二种

代码语言:javascript
复制
void dfs(int i, int tw, int tv, int op[])//求解0/1背包问题
{
	if (i > n)				//找到一个叶子结点
	{
		maxv = tv;			//存放更优解
		for (int j = 1; j <= n; j++)
			x[i] = op[j];
	}
	else                    //尚未找完所有物品
	{
		if (tw + A[i].w <= W)	//左孩子结点剪枝
		{
			op[i] = 1;			//选取序号为i的物品
			dfs(i + 1, tw + A[i].w, tv + A[i].v, op);
		}
		if (bound(i, tw, tv) > maxv)	//右孩子结点剪枝
		{
			op[i] = 0;			//不选取序号为i的物品,回溯
			dfs(i + 1, tw, tv, op);
		}
	}
}
12、学会画解空间树(省略)
13、判断子集和个数是否存在解

重点记dfs函数

考法一:

代码语言:javascript
复制
#include<stdio.h>
#define MAXN 20		//最多整数个数
//问题表示
int n = 4, W = 31;
int w[] = { 0,11,13,24,7 };//存放所有整数,不用下标0的元素
int count = 0;		//累计解个数
void dispasolution(int n)//输出一个解
{
	for (int j = 1; j <= n; j++)
		if (w[j] == 1)
			printf("\t将第%d个集装箱装上第一艘轮船\n", j);
		else
			printf("\t将第%d个集装箱装上第二艘轮船\n", j);
}
void dfs(int i, int tw, int rw, int x[])//求解子集和
{	//tw为考虑第i个整数时选取的整数和,rw为剩下的整数和
	if (i > n)//找到一个叶子结点
	{
		if (tw == W)//找到一个满足条件的解,输出它
			dispasolution(tw);
	}
	else            //尚未找完所有整数
	{
		if (tw + w[i] <= W)//左孩子结点剪枝:选取满足条件的整数w[i]
		{
			x[i] = 1;//选取第i个整数
			dfs(i + 1, tw + w[i], rw - w[i], x);
		}
		if (tw + rw - w[i] >= W)//右孩子结点剪枝
		{
			x[i] = 0;			//不选取第i个整数,回溯
			dfs(i + 1, tw, rw - w[i], x);
		}
	}
}
int main() {
	int x[MAXN];
	int rw = 0;//存放一个解向量
	for (int j = 1; j <= n; j++)
		rw += w[j];//求所有整数和rw
	dfs(1, 0, rw, x);//i从1开始
	return 0;
}

考法二:

代码语言:javascript
复制
#include<stdio.h>
#define MAXN 20		//最多整数个数
//问题表示
int n = 4, W;
int w[] = { 0,11,13,24,7 };	//存放所有整数,不用下标0的元素
bool dfs(int i, int tw, int rw)	//存放所有整数,不用下标0的元素
{
	if (i > n)						//找到一个叶子结点
	{
		if (tw == W)					//找到一个满足条件的解,返回true
		{
			return true;
		}
	}
	else                            //尚未找完所有物品
	{
		if (tw + w[i] <= W)				//左孩子结点剪枝
			return dfs(i + 1, tw + w[i], rw - w[i]);//选取第i个整数
		if (tw + rw - w[i] >= W)				//有孩子结点剪枝
			return dfs(i + 1, tw, rw - w[i]);	//不选取第i个整数,回溯
	}
	return false;
}

考法三:

代码语言:javascript
复制
int count;						//全局变量,累计解个数
void dfs(int i, int tw, int rw)	//求解子集和
{
	if (i > n)						//找到一个叶子结点
	{
		if (tw == W)					//找到一个满足条件的解,count++
		{
			count++;
		}
	}
	else                            //尚未找完所有物品
	{
		if (tw + w[i] <= W)				//左孩子结点剪枝
			dfs(i + 1, tw + w[i], rw - w[i]);//选取第i个整数
		if (tw + rw - w[i] >= W)				//有孩子结点剪枝
			dfs(i + 1, tw, rw - w[i]);	//不选取第i个整数,回溯
	}
}
结语

第五章回溯法结束,下一章——第六章分支限界法

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 第五章回溯法
      • 1、回溯法概念
      • 2、回溯法可以求解的问题有哪些
      • 3、回溯法算法设计的三个点
      • 4、回溯法解空间树的两种类型(重点简答)
      • 5、什么是活结点,什么是扩展结点,什么是死结点
      • 6、回溯法搜索解空间时通常采用的两种策略
      • 7、回溯法求解步骤
      • 8、回溯法与深度优先遍历的异同(简答)
      • 9、 回溯法=DFS+剪枝
      • 10、解空间树为子集树和排列树的时间复杂度
      • 11、 求解0/1背包问题(重点)
      • 12、学会画解空间树(省略)
      • 13、判断子集和个数是否存在解
    • 结语
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档