专题·深度优先搜索(DFS)【including 2N皇后,等边三角形,中国邮递员问题
初见安~这篇我们来讲讲深搜(DFS)
前文我们讲过了递归【这里是递推递归】,这里我们就要运用到啦~
所谓深搜,也顾名思义就是在深度上搜索,到了尽头则返回上一层,换一条路继续搜——也就是递归思想。
先看一道题了解一下吧:【中国邮递员问题】
对这道题就是很直白的dfs搜索目标。也正如题解里所言:很多dsf也可以用bfs实现,但与此同时也有很多是不能实现的。
比如搜索路径条数——
2N皇后
(本题出自计蒜客)
Description
给定一个 n*n 的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入 n 个黑皇后和 n 个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上,任意的两个白皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上。问总共有多少种放法?n 小于等于 8。
Input
输入的第一行为一个整数 n,表示棋盘的大小。接下来 n 行,每行 n 个 0 或 1 的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为 0,表示对应的位置不可以放皇后。
Output
输出一个整数,表示总共有多少种放法。
Sample Input 1
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
Sample Output 1
2
Sample Input 2
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
题解
了解题目后,我们可以有个大概的思路:黑白皇后之间无所谓冲突,所以我们只要分别处理好并标记位置确定同色皇后之间不冲突即可。那我们不妨大胆(不怕超时)尝试一下:先处理黑皇后(先白也可以),每放一个都四下检查一次有没有同色皇后;到了最后一行且皇后数量达到了2N时就开始找白皇后or跳出递归,已走过所有路径。
下面是代码及详解:
#include<bits/stdc++.h>
using namespace std;
int n,a[10][10],k=0;
int cnt=0;//cnt计数bool in(int x,int y) //检查是否越界
{return 1<=x&&x<=n&&1<=y&&y<=n;
}void dfs(int i,int q)//黑标记2白标记3 ,i为到第几行了。
{if(i>n) return;//越界for(int j=1;j<=n;j++){if(in(i,j)&&a[i][j]==1)//在(i,j)位置四下搜索是否遇得到已放皇后{bool flag=1;for(int k=1;k<=i-1;k++)//第i行后面的确定是没放的,所以不必搜索{if(a[k][j]==q) flag=0;}//不用搜索同一行,因为放了就深入到下一行int tx=i-1,ty=j+1;while(in(tx,ty))//斜向搜索{if(a[tx][ty]==q) flag=0;tx--;ty++;}tx=i-1,ty=j-1;while(in(tx,ty)){if(a[tx][ty]==q) flag=0;tx--;ty--;}if(flag)//通过了以上的检查操作{a[i][j]=q;if(i==n&&q==2)//黑皇后放完了{dfs(1,3);}else if(i==n&&q==3) //搜索完毕,计数{cnt++;}else dfs(i+1,q);a[i][j]=1;//递归循环,复原}}}
}int main()
{cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>a[i][j];dfs(1,2); cout<<cnt<<endl;return 0;
}
我知道还有个问题叫做8皇后问题。【和上述思路差不多,可以去试一下】
OK,我们再来看一道题:
等边三角形
(本题出自YCOJ)
Description
小白手上有一些小木棍,它们长短不一,小白想用这些木棍拼出一个等边三角形,并且每根木棍都要用到。 例如,小白手上有长度为 1,2,3,3 的4根木棍,他可以让长度为1,2 的木棍组成一条边,另外 2 跟分别组成 2 条边,拼成一个边长为 3 的等边三角形。小白希望你提前告诉他能不能拼出来,免得白费功夫。
Input
首先输入一个整数 n(3 ≤ n ≤ 200),表示木棍数量,接下来输入 n 根木棍的长度 p_i(1 ≤ p_i ≤ 10000)。
Output
如果小白能拼出等边三角形,输出"yes",否则输出"no"。
Sample Input 1
5
1 2 3 4 5
Sample Output 1
yes
Sample Input 2
4
1 1 1 1
Sample Output 2
no
题解
我们知道等边三角形就是三边相等。所以这道题我们可以凑(强行枚举?)出结果来。当然本题只需要返回是否存在解,所以找到了就可以了。
下面是代码及详解——
#include<bits/stdc++.h>
using namespace std;
int n,num[200],s=0;
bool flag=0;
void dfs(int a,int b,int c,int i)//三边长及用到了第几个木棍
{if(flag==1) return;//已经找到解了就不用在找了if(a==b&&b==c&&a!=0&&i==n+1)//如果找到了:{flag=1;return;}if(i>n+1||a>s||b>s||c>s)//返回上一个,因为长度超过了{return;}dfs(a+num[i],b,c,i+1);//强行凑!(什么鬼……)dfs(a,b+num[i],c,i+1);dfs(a,b,c+num[i],i+1);
}
int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>num[i];s+=num[i];}if(s%3!=0)//如果连总长都不能三等分的话,就不用考虑了。{cout<<"no"<<endl;return 0;}else{s=s/3;//s变为要凑出来的边长度dfs(0,0,0,1);}if(flag==1) cout<<"yes"<<endl;//flag标记else cout<<"no"<<endl;return 0;
}
最后,其实DFS有一个优化操作——迭代加深搜索。什么是迭代加深呢?就是搜索前先限定好深度搜,如果没搜到那么我们再更改深度。相当于是枚举答案。
画个图理解一下:假设我们枚举的深度一点点加深,那么搜索路径就是这样的:
只有当搜索深度为3的时候最后一个点才会被搜到。
这样搜看起来前面的点被重复搜了很多次,但其实效率多数时候是比一路搜到最深处的dfs要优秀一些的。
有一个不那么经典的迭代加深搜索题目:洛谷P2329 栅栏(fence8)。虽然是二分枚举的答案,但是也算是迭代加深的。
后期还有不少搜索的经典题目,欢迎到博客目录翻阅~
迎评:)
——End——
专题·深度优先搜索(DFS)【including 2N皇后,等边三角形,中国邮递员问题相关推荐
- 【算法很美】深入递归 (下)深度优先搜索DFS问题
深搜.回溯.剪枝 深度优先搜索DFS 2.1 无死角搜索I 数独游戏 部分和 水洼数目 2.2 回溯和剪枝 n皇后问题 素数环 困难的串 小结 一些使用 2.1 无死角搜索I 数独游戏 你一定听说过& ...
- 一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】
写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...
- C++实现深度优先搜索DFS(附完整源码)
C++实现深度优先搜索DFS C++实现深度优先搜索DFS完整源码(定义,实现,main函数测试) C++实现深度优先搜索DFS完整源码(定义,实现,main函数测试) #include <al ...
- C++用stack实现深度优先搜索DFS(附完整源码)
C++用stack实现深度优先搜索DFS的实现 C++用stack实现深度优先搜索DFS的完整源码(定义,实现,main函数测试) C++用stack实现深度优先搜索DFS的完整源码(定义,实现,ma ...
- 深度优先搜索(DFS) 总结(算法+剪枝+优化总结)
深度优先搜索(DFS) 总结(算法+剪枝+优化总结) 本文中会引用部分实例.文献资料来自不同的作者之手,由于资料整理比较困难,转载地址不在文中列举.如有侵权请联系我更换或删除!对于提供题解思路的各位大 ...
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍 ...
- 【数据结构与算法】2.深度优先搜索DFS、广度优先搜索BFS
原文链接:https://blog.csdn.net/qq_41681241/article/details/81432634 总结 一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的 ...
- 深入浅出,详解深度优先搜索(DFS)
深度优先搜索 如果把深度优先搜索比作一个人的话,那么这个人是一个执着的人,甚至倔强,不把一条路走到底不会返回(回溯),虽然执着倔强,但是他不傻,如果在探索的途中发现这条路走下去没有希望他会提前返回(剪 ...
- 深度优先搜索dfs算法刷题笔记【蓝桥杯】
其实网上已经有不少dfs的算法笔记,但我之所以还再写一篇,主要是因为我目前见到的笔记,都有些太偏向理论了. 对于基础薄弱的或是没有基础的人(like me),有点不合适,因为看了,也不能说自己会了. ...
最新文章
- Yii框架2.0的视图和widgets表单的使用
- 【干货】如何引导免费用户成为付费用户
- 2010世界杯主题曲夏奇拉献唱《Waka Waka》
- POJ 1062.昂贵的聘礼
- 创建provider服务
- mac上配置php开发环境,Mac配置PHP开发环境
- jdk1.8配置(自我速成)
- vs的form标签引起css走样问题
- typora代码块语言linux命令,typora工具的使用以及MarkDown语法
- js可以控制文件上传的速度吗?
- NLP—3.文本特征工程及工具使用举例
- Python的time,datetime,string相互转换
- JAVA 如何反编译JAR文件
- 腾讯云对象储存-图片上传-删除图片
- linux之cut命令的用法
- 移动拨号上网开热点(不是360开热点,而是使用电脑自带的热点功能)详解
- PHP时间差七个小时怎么回事,php 怎么解决8小时时间差的问题
- cefsharp内嵌资源html的读取,C#(csharp)用CefSharp开发实现一个浏览器,抓取网站任意资源...
- 黑客入门常用的8种工具
- 深度学习 - 42.特征交叉与 SENET、Bilinear Interaction 与 FiBiNet
热门文章
- 怀着忐忑的心情,我来了B站实习,B站后端日常实习面经分享!
- VScode Java代码自动生成器
- Tensorflow 4. 训练过程,服务器宕机了一次,服务器重启之后加载保存的model.ckpt报错?
- 六、微信小程序发布流程
- 开脑洞,买买买网站的皮肤
- 删除用户帐户后,保留在桌面上的用户配置文件夹删除后会自动重新生成的问题...
- C++RAII机制(智能指针原理)
- js下载文件流,提示文件损坏问题
- Django创建类不含默认id列
- 2021-2022-2 ACM集训队每周程序设计竞赛(10) - 问题 A: 还原撕碎的字条,哄笑生气的毛毛 - 题解