竞赛知识点4【搜索】

这篇具有很好参考价值的文章主要介绍了竞赛知识点4【搜索】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

复习

栈和队列的概念

  • 栈是限定仅在表头进行插入和删除操作的线性表(先进后出)。
  • 队列是只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。

  • 树是一种数据结构,它是由 n ( n ≥ 1 ) n (n\geq1) n(n1) 个有限节点组成一个具有层次关系的集合。把它叫做
    “树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的
    特点:
    • 每个节点有零个或多个子节点
    • 没有父节点的节点称为根节点
    • 每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子

    竞赛知识点4【搜索】

• 通过不停的试探去寻找解的一种算法。与其说是一种算法,不如说是一种方法。

• 基础的方法有暴力的搜索法,深搜,广搜三种。

• 更高级的有IDDFS,DBFS,A*,IDA*等等。

1.1、深度优先搜索(dfs)

1.1.1、概念

“一条道走到黑”、 “走不了了再倒回去。”

算法过程:

VOID DFS(状态 A)

  1. 判断当前的状态是否合法。合法则继续执行,否则则回到上次调用。
  2. 先下走一层,也就是调用DFS(状态 A + Δ)
竞赛知识点4【搜索】

1.1.2、例题

1、输出n个数的全排列

1,2,3组成的全排列为:

  • 123
  • 132
  • 213
  • 231
  • 312
  • 321
  • 可以写 n 重 for 循环
  • 可以用 stl 里面的 next_permutation

递归的来想这个问题,以1,2,3,4为例:
• 如果第一个数固定为1的话
• 后面就跟着2,3,4的全排列—— 所以就相当于是原问题的子问题的求解
• 考虑用递归解决

Void dfs(已经固定了前k-1个数剩下的数的全排列,是哪k-1个数通过标记该数字用没用过
来显示,当前这一步的任务就是把第k个数放上去)
{
	如果 已经求出来了 k>n 输出, 返回
 	否则 i从1到n循环
 	如果i没有用过,那么就将i固定在当前位置上,并调用 dfs(k+1)
 	在调用完dfs(k+1)后需要将固定在当前位置上的i拿走
}

void dfs(int dep)
{
	if(dep>n)
	{
		write();
		return;
	}	
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			a[dep]=i;
			dfs(dep+1);
			vis[i]=0;
		}
	}
}
2、输出n个数中选m个的组合
3、N皇后(8皇后的升级版)

N ∗ N N * N NN 的棋盘上放置 N ( n ≤ 13 ) N(n\leq13) N(n13) 个皇后而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上不能放置 2 2 2 个皇后),编程求解所有的摆放方法。

竞赛知识点4【搜索】

  • 由于皇后的摆放位置不能通过某种公式来确定,因此对于每个皇后的摆放位置都要进行试探和纠正,这就是“回溯”的思想。
    • 在 N N N 个皇后未放置完成前,摆放第 i i i 个皇后和第 i + 1 i+1 i+1 个皇后的试探方法是相同的,因此完全可以采用递归的方法来处理。
    • 由于皇后本身的特殊性质,即一行一列只能有一个皇后,所以我们所要做的就是,从第 0 0 0 行开始摆放,一直摆到第 n – 1 n – 1 n–1 行为止。

关于判断当前皇后可不可以放:

  • 我们是一行一行的放置皇后,所以不需要判断行冲突;
  • 判断列冲突时,可以通过设置一个布尔数组,如果已经有皇后放在那里,就把布尔值设为 1 1 1,如果可以放置并且没有冲突(即布尔值为 0 0 0),就放置当前这个皇后,且设置为 1 1 1
  • 判断对角线冲突时,有一个特殊的技巧:
    1. 由于每一条主对角线 ( x − y ) (x-y) (xy) 的值是一定的,每一条副对角线 ( x + y ) (x+y) (x+y)的值是一定的。所以就可以用 ( x + y ) (x+y) (x+y) 的值表示副对角线, ( x − y ) (x - y) (xy)的值表示主对角线。(于是就和处理列的情况一样了!)
    2. 假设我们把第 c u r cur cur 个皇后放在了 p o s [ c u r ] pos[cur] pos[cur] p o s [ c u r ] pos[cur] pos[cur] 储存了这个值),那么只需判断所检查的从前往后数第 k k k 个皇后有没有冲突就行了。
void dfs(int dep)
{
	if(dep>n)
	{
		write();
		return;
	}
	for(int i=1;i<=n;i++)
	{
		if(!vis[i] && !l[i+dep] && !r[i-dep+n])
		{
			vis[i]=1,l[i+dep]=1,r[i-dep+n]=1;
			a[dep]=i;
			dfs(dep+1);
			vis[i]=0,l[i+dep]=0,r[i-dep+n]=0;
		}
	}
}
4、马踏棋盘

给一个 5 ∗ 5 5*5 55 的国际象棋棋盘,国际象棋的马同样是走“日”字。
问,如果一个马,从第一个格子开始走,那么走遍整个 5 ∗ 5 5*5 55 的棋盘的方案,有多少种?并且输出方案数。

思路:

  1. 把问题抽象出来,就是有一只马要对整个图进行一次遍历,不重不漏。
  2. 其次考虑这个马的走法( 8 8 8 种)。
  3. 接着如何去在程序里面表现出这个棋盘。
  4. 最后就是套用回溯法的主要结构。

1.1.3、DFS大体框架

  • 试探节点A
  • A是否满足在这个图(或树)中
  • 如果在,标记A如果已经被试探过的话,所影响的各种值;
  • 紧接着,去试探所有的A可以达到的节点;
  • 等待所有的都执行完之后,还原标记A

1.1.4、剪枝

优化搜索的思路 — 减小搜索树的大小

方法:

  1. 改变搜索顺序
  2. 剪枝:最优化剪枝 & 可行性剪枝

题目1
N ∗ M N * M NM 的迷宫中给定起点 S S S 和终点 D D D ,问你是否能在 T T T 时刻恰好到达终点 D D D?

S.X.
..X.
..XD

分析:

  • 两个点之间是可以重复走的
  • A A A 点走到 B B B 点的奇偶性是不会改变的(剪枝1)
  • T a T_a Ta + T b T_b Tb 大于 T T T ,直接回溯(剪枝2)

题目2
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过 50 个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。(小木棍的数量小于等于 64)

分析文章来源地址https://www.toymoban.com/news/detail-433331.html

  1. 二分是否可行?
    no
  2. 如何枚举?
    所有小木棍长度中最大的那个数开始枚举,下一次枚举的数为所有小木棍长度总和的因子。
  3. 如何拼接?
    先拼接长的(搜索树的规模变小)
  4. 剪枝
  • 如果第 i i i 个棍子不能拼成假设的长度,则和第 i i i 个棍子相同长度的棍子也是不可能的,可以直接跳过去的。
  • 替换第 i i i 根棍子的第一根(或最后一根)木棒是没用的。
  • 如果某次拼接选择长度为 S S S 的木棒,导致最终失败,则在同一位置尝试下一根木棒时,要跳过所有长度为 S S S 的木棒。
bool dfs(int num,int len,int rest) //剩余的小木棍的数量 长度 还剩余要拼接的
{
	if(num==0 && rest==0) return true;
	if(rest==0) rest=len;
	for(int i=1; i<=n; i++)
	{
		if(vis[i])continue;
		if(a[i]>rest) continue;
		vis[i]=true;
		if(dfs(num-1,len,rest-a[i]))
			return true;
		vis[i]=false;
		if(a[i]==rest||len==rest)	break;
		while(a[i]==a[i+1])i++;
	}
	return 0;
}

到了这里,关于竞赛知识点4【搜索】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • WPF复习知识点记录

    由于近几年主要在做Web项目,客户端的项目主要是以维护为主,感觉对于基础知识的掌握没有那么牢靠,趁着这个周末重新复习下WPF的相关知识。 文章内容主要来自大佬刘铁锰老师的经典著作《深入浅出WPF》。 因为是复习,所以知识内容不会一一记录,如有需要了解更多可

    2024年02月11日
    浏览(40)
  • Pytorch基础知识点复习

    本篇博客是本人对pytorch使用的查漏补缺,参考资料来自 深入浅出PyTorch,本文主要以提问的方式对知识点进行回顾,小伙伴们不记得的知识点可以查一下前面的教程哦。   现在并行计算的策略是 不同的数据分布到不同的设备中,执行相同的任务(Data parallelism) 。   它的逻

    2024年01月20日
    浏览(40)
  • Web期末复习知识点

    下载Tomcat :前往Apache Tomcat官方网站(https://tomcat.apache.org)下载适合您操作系统的Tomcat版本。  安装Tomcat :解压下载的Tomcat压缩文件到您选择的目录。例如,将Tomcat解压到/opt/tomcat。 配置环境变量(可选) :如果需要在任何位置启动Tomcat,可以将Tomcat的bin目录添加到系统的

    2024年02月04日
    浏览(45)
  • 离散数学---期末复习知识点

    一、 数理逻辑   [ 复习知识点 ] 1、命题与联结词(否定¬、析取∨、合取∧、蕴涵→、等价↔),命题(非真既假的陈述句),复合命题(由简单命题通过联结词联结而成的命题) 2、命题公式与赋值(成真、成假),真值表,公式类型(重言、矛盾、可满足),公式的基本等值式

    2024年02月08日
    浏览(73)
  • Java期末复习——知识点+题库

    简单、面向对象、平台无关、多线程、动态 Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始 首字符之后可以是字母(A-Z 或者

    2024年02月02日
    浏览(63)
  • java基础知识点复习①

    java是一门开源的面向对象的编程语言,具有面向对象的封装、继承、多态的特点。 封装:将类的某些信息隐藏起来,只提供特定的方法来访问或修改这些隐藏信息,从而防止直接操作类中的某些属性。是通过访问权限修饰符来实现封装的,public——protected——default——pri

    2023年04月22日
    浏览(48)
  • Zookeeper 复习知识点(更新中)

    Zookeeper 是开源的,是一个基于观察者模式设计的分布式服务管理框架,负责存储和管理大家都关心的数据,然后接收观察者的注册,一旦这些数据发生变化,Zookeeper 负责通知已经注册的观察者。Zookeeper 相当于文件系统 + 通知机制。 1.1 Zookeeper 特点 集群架构 :Zookeeper 通常由

    2024年01月18日
    浏览(36)
  • Java集合基础知识点复习

    主要分为两类: 第一个是Collection 属于单列集合,第二个是Map 属于双列集合在Collection中有两个子接口List和Set。在我们平常开发的过程中用的比较多像list接口中的实现类ArrarList和LinkedList。 在Set接口中有实现类HashSet和TreeSet。 在map接口中有很多的实现类,平时比较常见的是

    2024年04月08日
    浏览(56)
  • 路由与交换技术(复习知识点-全)

    1、交换机和路由器的基础配置  2、远程登录交换机或者路由器 telnet          知道如何登入telnet 和一些基础内容 文件管理 3、路由表、静态路由、默认路由、动态路由(rip 和ospf ) 默认路由 4、动态路由RIP 和 OSPF协议和EIGRP协议 动态路由RIP EIGRP协议 OSPF协议 5、DHCP,路由

    2024年02月02日
    浏览(45)
  • Spark相关知识点(期末复习集锦)

    嗨喽,最近小伙伴们快要期末考试了吧,下面是我对《Spark零基础实战》的总结,希望能帮助到你们。 Spark,拥有hadoop MR所具有的优点,但不同于MR的是job中监测结果可以 保存在内存中 ,从而不再需要读写HDFS,因此spark能够更好的适用于数据挖掘与机器学习等需要迭代的m r的

    2024年02月02日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包