赞
踩
DFS(depth-first search)是一种搜索手段,它从某一个状态开始,不断转移,直到状态无法转移回退到前一步,继续转移到其他的状态,不断重复,知道找到它的解。根据这种性质,DFS用递归实现比较简单。
我们来看几道题来理解一下dfs.
第一道题就是求全排列
- #include <iostream>
- using namespace std;
- int a[10],flag[10],n;
- void dfs(int x){
- if(x==n+1){ //求n个数字的全排列,当x超过n输出结果
- for(int i=1;i<=n;i++){
- cout<<a[i]<<" ";
- }
- cout<<endl;
- return; //输出之后返回上一个状态
- }
- for(int i=1;i<=n;i++){
- if(flag[i]==0){
- a[x]=i; //将数组赋值之后,把这个数字打上一个标记
- flag[i]=1;
- dfs(x+1); //调用到下一层函数
- flag[i]=0; //取消标记
- }
- }
- return; //返回到上一个状态
- }
- int main(){
- cin>>n;
- dfs(1);
- return 0;
- }

通过这个题,我们可以总结出一个DFS的基本模板
-
- bool judge(/*参数*/){
- if(/*判断条件*/){
- return false;
- }
- return true;
- }
- void dfs(/*参数*/){
- /*判断是否是边界*/
- {
- /*输出*/
- }
- return;
- /*循环*/{
- /*判断是否满足条件*/
- /*标记*/
- dfs(/*下一个状态*/)
- /*去掉标记*/
- }
- }
-
-

第二道题,是洛谷里的点这里
输入样例:
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
输出样例:3
- //从任意w开始,不停地把邻接的部分用'.'替换,换了几次就证明有几个水洼
- #include <iostream>
- using namespace std;
- char a[101][101];
- int n,m;
- void dfs(int x,int y){
- a[x][y]='.';
- for(int dx=-1;dx<=1;dx++){
- for(int dy=-1;dy<=1;dy++){
- int nx=x+dx;
- int ny=y+dy;
- if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]=='W'){
- dfs(nx,ny);
- }
- }
- }
- return;
- }
- int sum;
- int main(){
- cin>>n>>m;
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- cin>>a[i][j];
- }
- }
- for(int i=0;i<n;i++){
- for(int j=0;j<m;j++){
- if(a[i][j]=='W'){
- dfs(i,j);
- sum++;
- }
- }
- }
- cout<<sum;
- }

最后一题,就是大名鼎鼎的八皇后问题点这里
其实我的代码是无法ac的,最后一个点会超时,还需要自己改进一下。
- #include <iostream>
- using namespace std;
- int a[14][14];
- int n,cnt;
- bool pd(int x,int y,int n){ //判断皇后是否危险
- for(int i=1;i<=n;i++){ //判断行
- if(a[i][y]==1){
- return false;
- }
- }
- for(int i=x,j=y;i>=1&&j>=1;i--,j--){ //判断对角线
- if(a[i][j]==1){
- return false;
- }
- }
- for(int i=x,j=y;i>=1&&j<=n;i--,j++){ //判断另一条对角线
- if(a[i][j]==1){
- return false;
- }
- }
- return true;
- }
- void dfs(int x){
- if(x==n+1){
- if(cnt<3){
- for(int i=1;i<=n;i++){
- for(int j=1;j<=n;j++){
- if(a[i][j]==1){
- if(i==n){
- cout<<j;
- }else{
- cout<<j<<" ";
- }
- }
- }
- }
- cout<<endl;
- }
- cnt++;
- return;
- }
- for(int j=1;j<=n;j++){
- if(pd(x,j,n)){
- a[x][j]=1;
- dfs(x+1);
- a[x][j]=0;
- }
- }
- }
- int main(){
- cin>>n;
- dfs(1);
- cout<<cnt;
- return 0;
- }

主要参考的是《挑战程序设计竞赛》
和一些大佬的文章点这里,大佬写的比我好很多。我的csdn可能记录的意义大于其他的意义啦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。