DFS(一):深度优先搜索的基本思想
采用搜索算法解决问题时,需要构造一个表明状态特征和不同状态之间关系的数据结构,这种数据结构称为结点。不同的问题需要用不同的数据结构描述。
根据搜索问题所给定的条件,从一个结点出发,可以生成一个或多个新的结点,这个过程通常称为扩展。结点之间的关系一般可以表示成一棵树,它被称为解答树。搜索算法的搜索过程实际上就是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的结点的过程。
深度优先搜索DFS(Depth First Search)是从初始结点开始扩展,扩展顺序总是先扩展最新产生的结点。这就使得搜索沿着状态空间某条单一的路径进行下去,直到最后的结点不能产生新结点或者找到目标结点为止。当搜索到不能产生新的结点的时候,就沿着结点产生顺序的反方向寻找可以产生新结点的结点,并扩展它,形成另一条搜索路径。
为了便于进行搜索,要设置一个表存储所有的结点。由于在深度优先搜索算法中,要满足先生成的结点后扩展的原则,所以存储结点的表一般采用栈这种数据结构。
深度优先搜索算法的搜索步骤一般是:
(1)从初始结点开始,将待扩展结点依次放到栈中。
(2)如果栈空,即所有待扩展结点已全部扩展完毕,则问题无解,退出。
(3)取栈中最新加入的结点,即栈顶结点出栈,并用相应的扩展原则扩展出所有的子结点,并按顺序将这些结点放入栈中。若没有子结点产生,则转(2)。
(4)如果某个子结点为目标结点,则找到问题的解(这不一定是最优解),结束。如果要求得问题的最优解,或者所有解,则转(2),继续搜索新的目标结点。
深度优先搜索算法的框架一般为:
void DFS()
{
栈S初始化;
初始结点入栈;
置搜索成功标志flag= false;
while (栈不为空 && !flag)
{
栈顶元素出栈,赋给current;
while (current 还可以扩展)
{
由结点current扩展出新结点new;
if (new 重复于已有的结点状态) continue;
new结点入栈;
if (new结点是目标状态)
{
置flag= true; break;
}
}
}
if (flag) 输出结果;
else 输出无解信息;
}
由于深度优先搜索是一个递归的过程,因此通常也使用递归函数来实现。一般框架为:
void DFS(结点类型 current) // 从结点current出发递归地深度优先搜索
{
置visited[current]=true; // 表示结点current已被处理
if (current结点是目标状态)
{
置搜索成功标志flag= false;
return ;
}
while (current 还可以扩展)
{
由current结点扩展出新结点new;
if (! visited[new]) DFS(new); // 对未处理的结点new递归调用DFS
}
置visited[current]=flase; // 表示结点current以后可能被处理
}
深度优先搜索中扩展结点的原则是先产生的后扩展。因此,深度优先搜索第一个找到的解,并不一定是问题的最优解,要搜索完整个状态空间,才能确定哪个解是最优解。
【例1】黑色方块
有一个宽为W、高为H的矩形平面,用黑色和红色两种颜色的方砖铺满。一个小朋友站在一块黑色方块上开始移动,规定移动方向有上、下、左、右四种,且只能在黑色方块上移动(即不能移到红色方块上)。编写一个程序,计算小朋友从起点出发可到达的所有黑色方砖的块数(包括起点)。
例如,如图1所示的矩形平面中,“#”表示红色砖块,“.”表示黑色砖块,“@”表示小朋友的起点,则小朋友能走到的黑色方砖有28块。
(1)编程思路。
采用非递归的深度优先搜索法解决这个问题。
用数组s模拟栈操作,栈顶指针为top,初始时,top=-1,表示栈空。
入栈操作为 s[++top]=t;
出栈操作为 t=s[top--] 。
程序中定义方砖的位置坐标(x,y)为Node类型,定义数组int visit[N][N]标记某方砖是否已走过,visit[i][j]=0表示坐标(i,j)处的方砖未走过,visit[i][j]=1表示坐标(i,j)处的方砖已走过。初始时visit数组的所有元素值均为0。
具体算法步骤为:
① 将出发点(startx,starty)入栈s,且置visit[startx][starty]=1,表示该处的方砖已被处理,以后不再重复搜索。
② 将栈s的栈顶元素出栈,得到一个当前方砖cur,黑色方砖计数(sum++),沿其上、下、左、右四个方向上搜索未走过的黑色方砖,将找到的黑色方砖的坐标入栈。
③ 重复执行②,直至栈s为空,则求出了所有能走过的黑色方砖数。
(2)源程序及运行结果。
#include <iostream>
using namespace std;
#define N 21
struct Node
{
int x;
int y;
};
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
char map[N][N];
int visit[N][N];
int dfs(int startx, int starty,int w,int h)
{
Node s[N*N],cur,next; // s为栈
int top,i,x,y,sum; // top为栈顶指针
top=-1; // 栈S初始化
sum=0;
cur.x=startx; cur.y=starty;
visit[startx][starty]=1;
s[++top]=cur; // 初始结点入栈;
while(top>=0) // 栈不为空
{
cur=s[top--]; // 栈顶元素出栈
sum++; // 方砖计数
for (i=0;i<4;i++)
{
x=cur.x+dx[i]; y=cur.y+dy[i];
if(x >=0 && x<h && y>=0 && y<w && map[x][y]!='#' && visit[x][y]==0)
{
visit[x][y] = 1;
next.x=x; next.y=y; // 由cur扩展出新结点next
s[++top]=next; // next结点入栈
}
}
}
return sum;
}
int main()
{
int i,j,pos_x,pos_y,w,h,sum;
while(1)
{
cin>>w>>h;
if (w==0 && h==0) break;
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
cin>>map[i][j];
if (map[i][j]=='@')
{
pos_x = i; pos_y = j;
}
visit[i][j] = 0;
}
}
sum=dfs(pos_x, pos_y,w,h);
cout<<sum<<endl;
}
return 0;
}
编译并执行以上程序,可得到如下所示的结果。
8 5
......#.
..##..@#
...#....
#......#
.#....#.
28
0 0
也可以采用递归的方法编写程序。
(3)深度优先搜索采用递归函数实现的源程序。
#include <iostream>
using namespace std;
#define N 21
char map[N][N];
int visit[N][N];
int w,h,sum;
void dfs(int x, int y)
{
if(x >=0 && x<h && y>=0 && y<w && map[x][y]!='#' && visit[x][y]==0)
{
visit[x][y] = 1;
sum++;
dfs(x+1,y); // 递归访问四个方向的砖块
dfs(x-1,y);
dfs(x,y+1);
dfs(x,y-1);
}
}
int main()
{
int i,j,pos_x,pos_y;
while(1)
{
cin>>w>>h;
if (w==0 && h==0) break;
for(i=0;i<h;i++)
{
for(j=0;j<w;j++)
{
cin>>map[i][j];
if (map[i][j]=='@')
{
pos_x = i; pos_y = j;
}
visit[i][j] = 0;
}
}
sum = 0;
dfs(pos_x, pos_y);
cout<<sum<<endl;
}
return 0;
}
DFS(一):深度优先搜索的基本思想的更多相关文章
- DFS(深度优先搜索)和BFS(广度优先搜索)
深度优先搜索算法(Depth-First-Search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种. 它沿着树的深度遍历树的节点,尽可能深的搜索树的分支. 当节点v的 ...
- DFS(深度优先搜索)
基本概念 深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法. 沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所在边都己被探寻过或者在搜 ...
- DFS(深度优先搜索)模板
void dfs()//参数用来表示状态 { if(到达终点状态) { ...//根据题意来添加 return; } if(越界或者是不符合法状态) return; for(扩展方式) { if(扩展 ...
- [LeetCode OJ] Word Search 深度优先搜索DFS
Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...
- [算法入门]——深度优先搜索(DFS)
深度优先搜索(DFS) 深度优先搜索叫DFS(Depth First Search).OK,那么什么是深度优先搜索呢?_? 样例: 举个例子,你在一个方格网络中,可以简单理解为我们的地图,要从A点到B ...
- 算法与数据结构基础 - 深度优先搜索(DFS)
DFS基础 深度优先搜索(Depth First Search)是一种搜索思路,相比广度优先搜索(BFS),DFS对每一个分枝路径深入到不能再深入为止,其应用于树/图的遍历.嵌套关系处理.回溯等,可以 ...
- 深度优先搜索(DFS)解题总结
定义 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.它沿着树的深度遍历树的节点,尽可能深的搜索树的分支. 例如下图,其深度优先遍历顺序为 1->2->4-&g ...
- Generate parentheses,生成括号对,递归,深度优先搜索。
问题描述:给n对括号,生成所有合理的括号对.比如n=2,(()),()() 算法思路:利用深度优先搜索的递归思想,对n进行深度优先搜索.边界条件是n==0:前面电话号组成字符串也是利用dfs. pub ...
- DFS_BFS(深度优先搜索 和 广度优先搜索)
package com.rao.graph; import java.util.LinkedList; /** * @author Srao * @className BFS_DFS * @date ...
随机推荐
- Android在putString和getString使用方法
函数: putString(String key,String value); 功能:将键为key的值为value. 详细的容器详细考虑比如对于Editor 的对象来讲: 代码例如以下: 首先新建一个 ...
- CF 455A(Boredom-dp)
A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- jquery 鼠标经过延时触发事件,jquery插件
jquery 鼠标经过延时触发事件. 用来做:鼠标经过选项卡,延时切换,鼠标经过商城分类延时显示,最好不过,防止用户随便滑动就切换了选项卡. 一.引入jq 二.加入以下插件代码 /* * 鼠标经过延时 ...
- Delphi 7下最小化到系统托盘(主要是WM_TRAYMSG和WM_SYSCOMMAND消息)
在Delphi 7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本.定义如下: 123456789 _NOTIFY ...
- 图像滤镜艺术---(Punch Filter)交叉冲印滤镜
原文:图像滤镜艺术---(Punch Filter)交叉冲印滤镜 (Punch Filter)交叉冲印滤镜 本文介绍一种交叉冲印效果的代码实现,至于原理,不在累赘,直接看代码: int f_TPun ...
- 浅谈Android高通(Qualcomm)和联发科(MTK)平台
一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...
- WPF应用程序嵌入第三方exe
把其它应用嵌入到C#窗口 源代码-CSDN下载 https://download.csdn.net/download/aiqinghee/10652732 WPF应用程序嵌入第三方exe - gao2 ...
- Oracle 存储过程创建及调用
--------创建存储过程------- create or replace procedure TestSPas begin update table_name set CREATE_TIMEST ...
- Android UI中英文自动显示问题
最近做了一个项目,其中有个视频和图片需要添加各种水印(日期,地点,经纬度,用户ID,产品ID等)问题,而且水印还要支持中英文自动切换显示.功能设计和实现算是比较顺利.昨天测试部给了一个小Bug,那就是 ...
- 使用 Elastic Stack 来监控和调优 Golang 应用程序
Golang 因为其语法简单,上手快且方便部署正被越来越多的开发者所青睐,一个 Golang 程序开发好了之后,势必要关心其运行情况,今天在这里就给大家介绍一下如果使用 Elastic Stack 来 ...