2021-08-01
作者:互联网
最近一直都在写洛谷的题目,其中有许多题目涉及到了DFS,在自己查找资料和学习总结后感觉递归这方便过于抽象,借此也像对此有更深的理解
所谓DFS就是指:优先考虑深度,换句话说就是一条路走到黑,直到无路可走的情况下,才会选择回头,然后重新选择一条路。
## **题目描述**
就先看下我遇到这种类型时候的第一次看到的题目
![在这里插入图片描述](https://www.icode9.com/i/ll/?i=0f99f14df30f4952ac52d6ac1d09864a.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pqc3J1X0JlZ2lubmVy,size_16,color_FFFFFF,t_70)
https://www.luogu.com.cn/problem/P1036
网站我也放这
## **草率的分析**
第一眼就是肯定就是枚举了,更深层次的算法我也没有学到.......
然后就是枚举的过程
首先就是组合数的知识 一眼就知道是c (n,k)算一下复杂度也可以接受
枚举所有的结果之后直接写一个判断素数的函数带入就可以了
那么重点就在怎么枚举这个
然后就没有然后了.....
## DFS原理和使用
引导题:输入一个数n,输出n的全排列
可以先把这个问题形象化
如:
假如有编号为1,2,3的3张扑克牌和编号为1,2,3的3个盒子。将这3张扑克牌分别放入3个盒子一共有几种不同的放法呢?
然后我们对这个简单的情况用dfs的思想
我们可以想象成将123三个数字放在有序的三个盒子里(这也是组合的思想)
在此当我们一个数已经放好了之后 设置一个book类型的数组对其标记
接下来我们只要按顺序放就好了完成123之后我们对其收回
按照上面的逻辑。小明将3号盒子的3号扑克牌取出,但手上仍然只有3号扑克牌。
所以小明只好回到2号盒子,收回2号扑克牌,此时手中有2,3号扑克牌。
按照之前的约定,往2号盒子放3号扑克牌,然后小明又继续往前走,此时手里只有2号扑克牌,把2号扑克牌放入3号盒子里,此时完成了第二种排序。(这里就是dfs的体现)
以此类推....
递归的思想在此就不再赘述
放一下这个的ac代码
```
#include<stdio.h>
int a[10],book[10],n;
//这里还有需要注意的地方C语言全局变量默认为0
void dfs(int step){ //此时在第step盒子面前,需要往里面放第i张扑克牌
int i;
if(step==n+1){ //这里说明前面的n个盒子已经放好了,这是dfs结束的标志
for(i=1;i<=n;i++)
printf("%d",a[i]);
printf("\n");
return ;
/*
注意这个 return 它的作用不是返回主函数,而是返回上一级的dfs函数
例:如果此时是 dfs(5),遇到这个 return 就会回到上一级的 dfs函数
也就是dfs(4),但此时dfs(4)的大部分语句已经执行了,只需要接着执行 book[i]=0
然后继续进入for循环进入下一次的 dfs函数,直到结束。
*/
}
for(int i=1;i<=n;i++){
if(book[i]==0){ //说明i号扑克牌还在手里,需要放入step号盒子
a[step]=i;//将i号扑克牌放到第step个盒子中
book[i]=1;//此时i号扑克牌已经被使用
dfs(step+1);
/*注意这里是自己调用自己,表示此时走到了第step+1个盒子面前*/
book[i]=0;
/*book[i]=0表示dfs调用结束了,换句话说就是扑克牌已经全部放完了
需要按照顺序将扑克牌收回,重新放,也就是前面所说的
*/
}
}
return;//这里表示这一级别的dfs函数已经结束了,返回上一级 dfs函数
}
int main(){
scanf("%d",&n);
dfs(1); //dfs函数的开始
return 0;
}
```
## 总结
我个人认为这个思想还是非常重要的
需要自己琢磨好久然后自己理解才能充分使用的
就我最近的做题情况来说遇到好多这个类型的了
上面的那个题目的ac代码自己的就不放了 (其实还有些情况没过)
网站在上面可以自己区里面找解析
撒花 2021/8/1 计算机202 zj
标签:01,盒子,扑克牌,08,dfs,step,book,2021,return 来源: https://blog.csdn.net/m0_56930054/article/details/119305320