回溯算法(基础)

news2024/10/6 10:36:40

目录

一、基本概念

二、以简单全排列认识回溯 

(一)决策树 

(二)回溯示意图  

(三)核心代码 

(四)完整代码 

三、组合问题

(一)问题   

(二)示意图 

(三)核心代码 

(四)完整代码 

(五)剪枝 

四、总结


一、基本概念

  • 回溯法是枚举法的一种,对于某些问题而言,回溯法是一种可以找出所有(或一部分)解的一般性算法,同时避免枚举的不正确的数值。一旦发现不正确的数值,就不再递归到下一层,而是回溯到上一层,以节省时间,是一种走不通就退回再走的方式

二、以简单全排列认识回溯 

(一)决策树 

  • 比如求三个数[1,2,3]的全排列,如果第一位先排1,那么第二位只能是2或3,如果第二位是2,那么第三位只能是3......

 

  • 只要从根遍历这棵树,记录路径上的数字,其实就是所有的全排列。不妨把这棵树称为回溯算法的「决策树」,为啥说这是决策树呢?因为在每个节点上其实都在做决策

  • 比如现在在蓝色节点,可以选择2,也可以选择3 
  • 同时每做一次选择,都展开一棵空间树 
  • 选择完后,如果是重复选是路径,就做剪枝 

  • 可做的选择已走的路径作为树节点的两个属性

(二)回溯示意图  

(三)核心代码 

void BackTrack(vector<int> nu, vector<int>& p, vector<vector<int>>& r)
{
	if (p.size() == nu.size())//结束条件
	{
		r.push_back(p);
		return;
	}
	for (int i = 0; i <= nu.size() - 1; i++)
	{
		if (judge(nu[i], p))//如果为假,本次循环后面的代码不会执行
		{
			continue;
		}
		p.push_back(nu[i]);//处理节点
		BackTrack(nu, p, r);
		p.pop_back();//撤销节点
	}
}

(四)完整代码 

#include<iostream>
#include<vector>
#include<stdbool.h>
using namespace std;
bool judge(int x, vector<int>p)//判断p中有没有元素x
{
	int i = 0;
	while (i < p.size())
	{
		if (x == p[i])
			return true;
		else
			i++;
	}
	return false;
}
void BackTrack(vector<int> nu, vector<int>& p, vector<vector<int>>& r)
{
	if (p.size() == nu.size())//结束条件
	{
		r.push_back(p);
		return;
	}
	for (int i = 0; i <= nu.size() - 1; i++)
	{
		if (judge(nu[i], p))//如果为假,本次循环后面的代码不会执行
		{
			continue;
		}
		p.push_back(nu[i]);//处理节点
		BackTrack(nu, p, r);
		p.pop_back();//撤销节点
	}
}
void print(vector<vector<int>> r)//遍历
{
	for (int i = 0; i < r.size(); i++)
	{
		for (int j = 0; j < r[i].size(); j++)
		{
			cout << r[i][j] << " ";
		}
		cout << endl;
	}
}
int main()
{
	int n;//元素个数
	cout << "输入元素个数:";
	cin >> n;
	vector<vector<int>>result;//存放符合条件结果的集合
	vector<int>path;//已走的路径
	vector<int>num(n);//存放元素
	cout << "依次输入各元素:";
	for (int i = 0; i < n; i++)
	{
		cin >> num[i];
	}
	BackTrack(num, path, result);
	cout << "全排列结果:" << endl;
	print(result);//遍历
}

三、组合问题

(一)问题   

  • 有任意n个数,返回所有可能的 k 个数的组合 

(二)示意图 

(三)核心代码 

void BackTrack(int start, int k, vector<int> nu, vector<int>& p, vector<vector<int>>& r)
{
	if (p.size()==k)//结束条件
	{
		r.push_back(p);
		return;
	}
	for (int i = start; i <= nu.size() - 1; i++)
	{
		p.push_back(nu[i]);//处理节点
		BackTrack(i + 1, k, nu, p, r);
		p.pop_back();//回溯
	}
}

(四)完整代码 

#include<iostream>
#include<vector>
#include<stdbool.h>
using namespace std;
void BackTrack(int start, int k, vector<int> nu, vector<int>& p, vector<vector<int>>& r)
{
	if (p.size()==k)//结束条件
	{
		r.push_back(p);
		return;
	}
	for (int i = start; i <= nu.size() - 1; i++)
	{
		p.push_back(nu[i]);//处理节点
		BackTrack(i + 1, k, nu, p, r);
		p.pop_back();//回溯
	}
}
void print(vector<vector<int>> r)//打印
{
	for (int i = 0; i < r.size(); i++)
	{
		for (int j = 0; j < r[i].size(); j++)
		{
			cout << r[i][j] << " ";
		}
		cout << endl;
	}
}
int main()
{
	int n,k;//元素个数和每个组合元素个数
	cout << "输入元素个数:";
	cin >> n;
	vector<vector<int>>result;//存放符合条件结果的集合
	vector<int>path;//已走的路径
	vector<int>num(n);//存放元素
	cout << "依次输入各元素:";
	for (int i = 0; i < n; i++)
	{
		cin >> num[i];
	}
	cout << "输入组合元素个数:";
	cin >> k;
	BackTrack(0, k, num, path, result);
	cout << "结果:" << endl;
	print(result);//打印
}

//输入元素个数:5
//依次输入各元素:1 2 3 4 5
//输入组合元素个数:2
//结果:
//1 2
//1 3
//1 4
//1 5
//2 3
//2 4
//2 5
//3 4
//3 5
//4 5

(五)剪枝 

  • 优化过程:
  1. 已经选择的元素个数:path.size()
  2. 还需要的元素个数为: k - path.size()
  3. 在集合中至多要从num.size() - (k-p.size())位置,开始遍历

#include<iostream>
#include<vector>
#include<stdbool.h>
using namespace std;
void BackTrack(int start, int k, vector<int> nu, vector<int>& p, vector<vector<int>>& r)
{
	if (p.size()==k)//结束条件
	{
		r.push_back(p);
		return;
	}
	for (int i = start; i <= nu.size() - (k-p.size()); i++)
	{
		p.push_back(nu[i]);//处理节点
		BackTrack(i + 1, k, nu, p, r);
		p.pop_back();//回溯
	}
}
void print(vector<vector<int>> r)//打印
{
	for (int i = 0; i < r.size(); i++)
	{
		for (int j = 0; j < r[i].size(); j++)
		{
			cout << r[i][j] << " ";
		}
		cout << endl;
	}
}
int main()
{
	int n,k;//元素个数和每个组合元素个数
	cout << "输入元素个数:";
	cin >> n;
	vector<vector<int>>result;//存放符合条件结果的集合
	vector<int>path;//已走的路径
	vector<int>num(n);//存放元素
	cout << "依次输入各元素:";
	for (int i = 0; i < n; i++)
	{
		cin >> num[i];
	}
	cout << "输入组合元素个数:";
	cin >> k;
	BackTrack(0, k, num, path, result);
	cout << "结果:" << endl;
	print(result);//打印
}

//输入元素个数:5
//依次输入各元素:1 2 3 4 5
//输入组合元素个数:2
//结果:
//1 2
//1 3
//1 4
//1 5
//2 3
//2 4
//2 5
//3 4
//3 5
//4 5

四、总结

  • 回溯算法模板
void backtracking(参数)
{
	if (终止条件)
	{
		存放结果;
		return;
	}
	for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小))
	{
		处理节点;
			backtracking(路径,选择列表);//递归
		回溯,撤销处理结果
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何通过groovy扩展方法

最近一直使用jmeter做接口测试&#xff0c;虽然好用&#xff0c;但是每次解析结果都要写大量重复代码。然后想到groovy是可以在运行时动态增强jvm字节码的&#xff0c;比如Date中就有大量增强的方法&#xff0c;比如format,upto,downto......&#xff0c;既然groovy可以&#x…

用 NFTScan 的角度解析 Yuga labs NFT 项目系列

如果要说 NFT 影响力最大的公司是哪个&#xff1f;如果说是 Yuga Labs 应该我想大家应该都不会否认。一个创立一年多的 NFT 营销和开发公司&#xff0c;多次的并购以及行销操作都立下 NFT 界的标竿典范&#xff0c;尤其 BAYC NFT 系列取得巨大成功之后&#xff0c;该团队已成为…

DSP_定义一个大的全局数组_探索之路

前言 最近在做基于dsp平台的无通信接口系统辨识&#xff0c;辨识的时候会有很大的数据需要存到一个数组当中&#xff0c;而dsp如果定义一个很大的全局数组&#xff0c;编译会报错。 本文将探索如何解决这个报错以及全局数组的大小极限。 正文 首先&#xff0c;我们定义了一个…

数学库:Extreme Optimization Numerical 8.1.4 Crack

Extreme Optimization Numerical.NET 的极端优化数值库&#xff0c;更快地构建金融、工程和科学应用程序&#xff0c;具有置信度和预测带的非线性曲线拟合&#xff0c;用于 .NET的极端优化数值库是为 Microsoft .NET 框架构建的通用数学和统计类的集合。用于 .NET的极端优化数值…

将无风险资产与单个风险资产进行组合

目录 1. 基本概念 2. 将无风险资产与单个风险资产进行组合 3. 有效资产组合 1. 基本概念 无风险资产和风险资产。 我的理解&#xff1a;无风险资产利率完全可确定&#xff0c;风险资产的利率称为预期收益率&#xff0c;并且有标准差。 关于风险资产预期收益率和标准差的计…

NC65 自由报表发布为节点如何显示以及如何取消已发布的报表节点

NC65 自由报表发布为节点如何显示以及如何取消已发布的报表节点&#xff1f; 一、NC65 自由报表发布为节点如何显示&#xff1f; 答&#xff1a;需要在动态建模平台-权限管理-职责管理下的职责节点进行功能分配&#xff0c;如下图&#xff1a; 二、如何取消已发布的报表节…

Javac Spire.Presentation 之PPT文本图片内容提取

目录结构前言文档准备引入Maven依赖代码块提取结果验证ppt_demo.ppt 提取结果pptx_demo.pptx 提取结果前言 应公司需求&#xff0c;需实现以下功能 PPT文本内容的替换&#xff1b;PPT文本内容的提取&#xff1b;PPT中图片的提取存放&#xff1b; 此文章将使用Spire.Presenta…

Mal-PEG-SCM,Maleimide PEG SCM,双功能修饰性PEG

Mal-PEG-SCM&#xff0c;SCM-PEG-Maleimide&#xff0c;Maleimide PEG SCM&#xff0c;Maleimide PEG Succinimidyl Carboxymethyl Ester马来酰亚胺-聚乙二醇-琥珀酰亚胺羧甲基酯&#xff0c;马来酰亚胺PEG琥珀酰亚胺羧甲基酯Product specifications&#xff1a;1.CAS No&#…

DataGrip下载安装及使用教程(详细版)

一.安装教程 1.下载 官网下载&#xff1a;DataGrip: The Cross-Platform IDE for Databases && SQL by JetBrains 2.点击Download跳转到下载页面 3.下载最新版本的可以直接点击 Download 下载&#xff0c;下载其他版本的点击 Other versions 下载其他版本 4. 4.选择…

改变Linux文件权限、所属用户组、所有者知识总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Linux操作…

requestAnimationFrame详解-js性能优化

requestAnimationFrame 请求动画帧 它是一个浏览器的宏任务 requestAnimationFrame的用法与settimeout很相似&#xff0c;只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数&#xff0c;这个回调函数会在浏览器重绘之前调用。它返回一个整数&#x…

快鲸SCRM打通工单系统,实现客户售前售后一体化管理

深度运营客户关系&#xff0c;做好客户售后服务&#xff0c;才符合企业的长远利益。然而大多数企业只注重售前售中&#xff0c;忽视了售后&#xff0c;导致客户售后服务现状不尽人意&#xff0c;主要体现在&#xff1a; 把客户问题抛到售后群后&#xff0c;便放任不管; 缺乏标…

自动驾驶感知——超声波技术

文章目录1. 超声波基本概念1.1 声波的频率与分类1.2 超声波的波速和波长1.3 超声波的指向性1.4 超声波的反射和折射1.5 超声波的衰减1.6 超声波产生的效应2. 超声波传感器原理及传感器分类2.1 超声波传感器原理2.2 压电式超声波传感器2.3 磁致伸缩式超声波传感器2.4 超声波传感…

MyBatis案例 | 使用映射配置文件实现CRUD操作——通过主键查询对应数据

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;JavaWeb Java入门篇&#xff1a; &#x1f525;Java基础学习篇 Java进阶学习篇&…

关于Linux中断的相关查询

1.linux 内核 /proc/interrupts 在 /proc/interrupts 文件中记录了 Linux 内核的中断信息&#xff0c;我们可以通过命令查看 sudo cat /proc/interrupts 文件中以表格的形式列举出来所有的内核中断&#xff0c;其表头信息标注如下&#xff1a; 我们可以通过特定任务执行时…

计算机SCI论文一定要在指定的机构润色吗? - 易智编译EaseEditing

不一定要在指定的机构润色。 首先期刊要求润色&#xff0c;是非常正常的事情。国人投的中文论文&#xff0c;有的也会被要求润色。 更不要说国外的英文期刊了&#xff0c;咱们写的英文文章投过去&#xff0c;大部分都会被要求润色的。 为什么期刊总是要求润色语言呢&#xff…

Windows7操作系统安全(3)

实验简介 实验所属系列&#xff1a;网络安全实践 实验对象&#xff1a; 本科/专科信息安全专业 相关课程及专业&#xff1a;计算机基础&#xff0c;Linux基础 实验时数&#xff08;学分&#xff09;&#xff1a;2学时 实验类别&#xff1a;实践实验类预备知识 Windows系列是目…

Oracle重建控制文件

利用trace文件重建控制文件 1、生成trace文件&#xff1a; SQL>alter database backup controlfile to trace;2、找到生成的trace文件&#xff1a; SQL>show parameter user_dump_destuser_dump_dest 文件对应的路径即为trace文件的路径 3、关闭数据库 SQL>shutdo…

VueJS 之模板引用

文章目录参考描述模板引用引用访问模板引用组件中的模板引用$nextTick()示例updated错误示范正确演示$nextTick()参考 项目描述搜索引擎Bing哔哩哔哩黑马程序员VueJS 官方文档模板引用 描述 项目描述Edge109.0.1518.70 (正式版本) (64 位)操作系统Windows 10 专业版vue/cli5.…

jvm相关,jvm内存溢出,内存占用过高,CPU占用率高原因分析,MAT内存镜像文件分析的使用----学习笔记

什么是内存泄漏? 什么是内存溢出 内存溢出: OutOfMemory 它是指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;抛出 OutOfMemory 错误 内存泄露: Memory Leak 它是指程序运行后&#xff0c;没有释放所占用的内存空间&#xff0c;比如程序运行完后没有释…