本专题主要锻炼搜索的两大方法——bfs (宽度优先搜索)和 dfs (深度优先搜索)
===================================华丽的分割线=======================================
一、bfs——宽度优先搜索(Breadth First Search)
bfs主要运用于搜索中求最短时间的问题,搜索过程中一般需要运用 queue 的操作。
bfs的核心思想是:从初始结点开始,应用算符生成第一层结点,检查目标结点是否在这些后继结点中,若没有,再用产生式规则将所有第一层的结点逐一扩展,得到第二层结点,并逐一检查第二层结点中是否包含目标结点。若没有,再用算符逐一扩展第二层所有结点……,如此依次扩展,直到发现目标结点为止。
具体的操作如下:
1.首先需要将 队列 和 visit数组 清空。(这一点很重要!!!)
2.然后将起点信息 push 进队列,标记为visited(修改 visit 数组中元素对应的值),信息一般都用结构体存储,当然,所建立的 queue 也必须是结构体类型的。
3.接下来就是主体了——一个while循环,判断条件为 队列非空。
每次循环,需要取出队首元素,然后 pop 出队首元素。首先判断是否已满足题目要求,满足的话 return 所需要的信息,否则以该元素为中心,遍历四周的节点,如果节点可以到达且未被访问,则将该节点的信息 push 进队列,并标记为visited。重复循环即可。
4.如果到达while循环外面,说明题目的要求无法达到,返回 impossible 即可。
伪代码如下:(凯神提供!!!快去仰慕)
Q empty
init state - s
Q push s
visite s
while(Q ! empty)
{
state now = Q front
Q pop
next = update now
if(next not visited)
{
Q push next
visite next
}
}
return impossible
几个注意点:
1.各个数据的清空和初始化
2.遍历四周的节点可以用一个for循环,具体实现方法请看最后的题解。
===============================华丽的分割线的大儿子=================================
二、dfs——深度优先检索(Depth First Search)
dfs主要运用于求解满足题目的所有可能的解法的数目,显然这种问题无法用 bfs 解决,因为 bfs 只能求解最优解,而用 dfs 就可以了。
dfs所遵循的搜索策略是尽可能“深”地搜索图。在深度优先搜索中,对于最新发现的结点,如果它还有以此为起点而未搜过的边,就沿着边继续搜索下去。当结点v的所有边都已被探寻过,搜索将回溯到发现结点v有那条边的始结点。这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点,则选择其中一个作为源结点并重复以上过程,整个过程反复进行直到所有结点都被发现为止。
深度优先搜索遍历类似于树的先序遍历。假定给定图G的初态是所有顶点均未被访问过,在G中任选一个顶点i作为遍历的初始点,则深度优先搜索递归调用包含以下操作:
(1)访问搜索到的未被访问的邻接点;
(2)将此顶点的visited数组元素值置1;
(3)搜索该顶点的未被访问的邻接点,若该邻接点存在,则从此邻接点开始进行同样的访问和搜索。
dfs可描述为:
(1)访问v0顶点;
(2)置 visited[v0]=1;
(3)搜索v0未被访问的邻接点w,若存在邻接点w,则dfs(w)。
遍历过程:
dfs 在访问图中某一起始顶点 v 后,由 v 出发,访问它的任一邻接顶点w1;再从 w1 出发,访问与 w1邻 接但还没有访问过的顶点 w2;然后再从 w2 出发,进行类似的访问,… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 u 为止。
接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。
深度优先搜索基本算法如下{递归算法}:
PROCEDURE dfs_try(i);
FOR i:=1 to maxr DO
BEGIN
IF 子结点 mr 符合条件 THEN
BEGIN
产生的子结点mr入栈;
IF 子结点mr是目标结点
THEN 输出
ELSE dfs_try(i+1);
栈顶元素出栈;
END;
END;
==============================华丽的分割线的小儿子==================================
题目链接:https://vjudge.net/contest/65959
简单搜索专题题解
A. POJ 1321 棋盘问题
题目要求求出可行解的数目,显然要用dfs,代码如下:
1 #include<iostream> 2 #include<cstring> 3 4 using namespace std; 5 6 char a[8][8]; 7 int num,n,k; 8 9 struct node 10 { 11 int c[8]; 12 int count; 13 }; 14 15 void dfs(int x,struct node map) 16 { 17 if(x>=n) 18 return; 19 /*if(map.count==k) 20 { 21 num++; 22 return; 23 }*/ 24 for(int i=0;i<n;i++) 25 { 26 if(a[x][i]=='.') 27 continue; 28 29 if(map.c[i]==0) 30 { 31 struct node map1; 32 // memcpy(map1.b,map.b,sizeof(map.b)); 33 memcpy(map1.c,map.c,sizeof(map.c)); 34 map1.count=map.count; 35 36 map1.count++; 37 map1.c[i]=1; 38 if(map1.count==k) 39 { 40 num++; 41 // dfs(x+1,map); 42 // cout<<num<<endl; 43 continue; 44 } 45 else 46 { 47 dfs(x+1,map1); 48 } 49 } 50 } 51 dfs(x+1,map); 52 } 53 54 int main() 55 { 56 while(cin>>n>>k) 57 { 58 if(n==-1&&k==-1) 59 break; 60 for(int i=0;i<n;i++) 61 { 62 for(int j=0;j<n;j++) 63 cin>>a[i][j]; 64 } 65 num=0; 66 struct node map; 67 // memset(map.b,0,sizeof(map.b)); 68 memset(map.c,0,sizeof(map.c)); 69 map.count=0; 70 //cout<<num<<endl; 71 dfs(0,map); 72 cout<<num<<endl; 73 } 74 return 0; 75 }