深搜,顾名思义 就是以深度为上的搜索算法,它本质上就是个递归
只不过是一个比较奢华的的递归
深搜简称 | 使用背景 | 参考模型 | 题型 |
---|---|---|---|
dfs | 找出所有解;全排列;找到所用的方法数;图论; | 栈和递归 | 全排列;二维深搜; |
TIPS:dfs一般从1开始搜索,与常用的递归不同,有些深搜中是不需要调用自身的,比如下面这道题:
洛谷传送门:P1706 全排列问题
密码岛OJ传送门:#1244. 全排列
按照字典序输出自然数 11 到 nn 所有不重复的排列,即 nn 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
一个整数 n。
由 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留5个场宽。
3
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
1≤n≤9。
这道题的本意就在于求排列,类似于排列组合里的A 每个数都要排不止一次。
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。——百度百科
所以通过题目的意思我们可以知道,全排列的次数的出口在于当m=n时,就结束
我们看到题目,第一反应一定是用循环做。比如本蒟蒻一开始的想法:
#include
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cout<
可是情况不是很对路。
人家要的是全排列!!全排列!!你这就只输出了个数!!
没关系 ,事情要从根本入手。我们看看如果要一次输出两个数该怎么样。
#include
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<
一个非常没有技术含量 非常Wonderful的枚举。
如果一次要输出三个数怎么办??
#include
using namespace std;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
cout<
一个很没有技术含量的枚举。这时候你已经面临TLE 的危险了。
这时候,你很无厘头的想到,再这么枚举下去你也不知道要写几个循环。
于是你想用函数,但是你又不知道函数要调用几次。
但深搜怎么写,第一步你还是只知道用循环。那就写个循环8
for(int i=1;i<=n;i++){
printf("%5d",a[i]);
}
cout<
非常Wonderful。珂朵莉都给你点赞。
但是你还要控制范围,所以再写一个if:
if(x>n){
for(int i=1;i<=n;i++){
printf("%5d",a[i]);
}
cout<
但是你这只是满足了输出的情况,你还要判断如果不能输出的时候应该执行什么操作,所以我们可以用else语句:
else{ }
但是在else里面写什么??回到深搜最开始的题面
题目想让你干什么 要输出1-n的全排列 如果保证不重复的情况下,那你还需要一个标记的东西来标记它是否重复出现过。
用什么标记?用单个变量吗 必然是不行的。人家有一堆数要你排 那就开个数组8
bool b[1000]={0};
老样子,一个 for循环。先判断它是否被使用过,也就是判断b[i]是否==1。如果是的话就说明被使用过,就直接continue,剪枝。别忘了遍历完要再标记成1.
else{
for(int i=1;i<=n;i++){
if(b[i]==1){
continue;
}
b[i]=1;
}
}
标记之后呢?你深搜完之后说明,在这一次操作里你的数已经排完了,你要开始重新挑三个数了。那这时候你就要把原本标记的1改成0。
else{
for(int i=1;i<=n;i++){
if(b[i]==1){
continue;
}
b[i]=1;
b[i]=0;
}
}
你既然要做深搜,那就看回上面输出的时候你输出了什么。你输出了a[i]. 那你肯定就要把你的value存进a[ ]数组里,由于x是每层递减的,象征了搜索的次数,所以你大可以用x当做a的下标,然后存i.
深搜部分完整代码如下:
int n;
int a[100];
bool b[1000];
void dfs(int x){
if(x>n){
for(int i=1;i<=n;i++){
printf("%5d",a[i]);
}
cout<
但是你还要有main函数的呀 main是从1开始搜,所以加上主函数整道题的完整代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
完美,AC 撒花,这道题就完美的过了。
今天是全排列篇,不想写了 写太长了,下次再讲拓展8
888888888888886