详解深度优先搜索

来源:互联网 发布:暗黑破坏神2修改器mac 编辑:程序博客网 时间:2024/05/29 11:59

在图、树有关的问题中用处很大。

1、基本框架

对于初学者《啊哈!算法》(纪磊著,人民邮电出版社)是一本不错的书,比较儿童化,例子很形象,这里的一些东西摘录自这本书,在此致谢。。。

但是我要吐槽一下作者使用数组居然是从1开始的。。。这。。。。。。很不计算机=。=

基本框架:

/*DFS的框架*/void dfs(int step){judge the border//判断边界for(int i=0;i<n;i++)//尝试每种可能dfs(step+1);//继续下一步return;//返回}


2、实例

放几个简单的例子方便复习。与DFS相关的试题(主要来自LeetCode)会不定期单独发文。

(1)改变自《啊哈!算法》:帮帮小明

小明有一道家庭作业:有1——9共九个数字,要求将它们填入式子[][][]+[][][]=[][][]中使等式成立,小明很快得出了一个解:111+821=932,但是他想知道一共有多少种不同的解,请你帮帮他。

书里是用扑克牌+装盒子来形象化这个问题的:假设现在手上有写好1——9的9张扑克牌,把[]看成盒子,我们的任务是把扑克牌放进盒子使得[][][]+[][][]=[][][]。

代码:

#include<iostream>using namespace std;int book[10],box[10],tot=0;//用book表示牌是否在手里,box表示盒子,tot用来计数void dfs(int step){int i;if(step==10){//边界:走到了第十个盒子(不存在),说明牌已经全部放好了if(box[1]*100+box[2]*10+box[3]+box[4]*100+box[5]*10+box[6]==box[7]*100+box[8]*10+box[9])tot++;return;//返回最近调用的地方}for(i=1;i<=9;i++){if(book[i]==0){//如果牌在手里box[step]=i;//放入盒子book[i]=1;//做标记dfs(step+1);book[i]=0;//把放下去的牌收回来才能进行下一次尝试}}return;}int main(){dfs(1);printf("total:%d\n",tot/2);return 0;}

一共168种

关于这个问题的图解:



可以看成出if{}里的那个return是非常必要的,如果不return程序就回不去了。

(2)走迷宫

这个问题和63. Unique Paths II很相似(链接:http://blog.csdn.net/lishichengyan/article/details/77204731)。

有一个n行m列的迷宫,例如n=5,m=4:

0 0 1 0

0 0 0 0

0 0 1 0

0 1 0 0

0 0 0 1

其中1表示障碍物,0表示空地。现在给定你的位置坐标和你女朋友(或者男朋友)的位置坐标,例如1 1 4 3,表示你处在(1,1),你的女票/男票处在(4,3),假定女票/男票不移动,那么找到女票/男票最少需要多少步?

#include<iostream>using namespace std;#define MAXSIZE 51int n,m,p,q,min_step=INT_MAX;int a[MAXSIZE][MAXSIZE],book[MAXSIZE][MAXSIZE];//a[]存放地图,book[]为1表示走过,0表示没走过void dfs(int x,int y,int step){int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//向右、下、左、上四个方向走int tx,ty;if(x==p&&y==q){if(step<min_step)min_step=step;return;}for(int k=0;k<4;k++){//枚举四种走法tx=x+next[k][0];ty=y+next[k][1];if(tx<1||tx>n||ty<1||ty>n)continue;if(a[tx][ty]==0&&book[tx][ty]==0){book[tx][ty]=1;dfs(tx,ty,step+1);book[tx][ty]=0;}}return;}int main(){int startx,starty;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&a[i][j]);}}scanf("%d%d%d%d",&p,&q,&startx,&starty);dfs(startx,starty,0);printf("minimum steps:%d\n",min_step);return 0;}

作者的习惯是数组下标从1开始所以这里的(1,1)相当于(0,0)。。。还是有点别扭=。=


待续未完。。。






原创粉丝点击