这一周通过对搜索题目的大量练习,对于搜索也是有了一定的理解,首先对于深搜来说,有几种题型:
一、有一部分题目指示的很明确,也是基本的深搜类型,比如连通块类型,是显式的深搜
P1596 [USACO10OCT]Lake Counting S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
就像这题的水洼地,可以看到,基本方法是对当前位置的四个方向进行搜索,检测指定的标识
void dfs (int x,int y){
field [x][y]='.';
for(int dx=-1;dx<=1;dx++) {
for(int dy=-1;dy<=1;dy++) {
int nx=x+dx,ny=y+dy;
if(0<=nx&&nx<n&&0<=ny&&ny<m&&field[nx][ny]=='W')
dfs(nx,ny);
}
}
return ;
}
还有类似的下题也是一样的操作
P1451 求细胞数量 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
void dfs(int i,int j)
{ f[i][j]='0';
for(int k=0;k<4;k++)
{
int x=i+d[k][0],y=j+d[k][1];
if(x>=0&&x<n&&y>=0&&y<m&&f[x][y]!='0')
{
dfs(x,y);
}
}
}
我们会发现,一般这种题会有几个类似的地方,就是一般都是对点的行进进行搜索,相应的就会有点的行进方向, 就如这两题一个是对八个方向搜索一个是对四个方向搜索,这是其中简单的连通块类型对点的行进方向进行搜索。对符合要求的地方进行插点标记等操作。
二、有时同样也是显式的连通块搜索但是也需要些技巧
比如 :P1506 拯救oibh总部 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
示例: 4 5 00000 00*00 0*0*0 00*00
通过示例可以看到也是连通块问题,但是问题的问法变成了被 “*”围起来的“0”的个数,那么这样和之前一样只需对点的行进进行搜索即可,但是这个题还有个特殊的样例:
示例:
4 5
0*000
*0000
00000
00000
我们搜索时会发现只是从头(1 ,1)位置搜,第一次就会进行不下去,那么这就需要从另一个角度分析如何绕过这个
0000000
00*0000
0*00000
0000000
0000000
0000000
我们选择多搜一圈,那么就能规避这个问题,
三、对于某些题来说,对于图的遍历还有另一种搜索方式就是每个图相当于二维数组我们对二维数组搜索时一行行的搜索每行一个个进行,当列数搜索到边界时进行下一行的搜索,直到行数也搜索到边界
如:
P1123 取数游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
if(y==m+1){//当y搜索到边界时,搜索下一行
dfs(x+1,1);
return;
}
if(x==n+1){//当x到边界时说明条件符合 ,搜索完毕
...
return;
}
我们做题时还会发现,做一道题的方法往往不只是一种
那么做题时有些题的提示也会很明显,如马的遍历,题目就会要求求最少路径,那么一般选用广搜就会很方便,广搜在理解起来也会很好理解一些,只需套用模板利用队列,找出边界问题即可,另一方面,题目明显是对图的遍历问题而没有提到最少之类的词的即可用深搜进行,深搜不止用来二维平面,
如:rP3958 [NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
是三维空间系,但是用深搜一样很好理解,
最后重要的是对方法的灵活运用,不是机械的套用模板,死背知识,知识固然重要,但是只是基础,重要的是如何将知识去贴合实际,转化成解决问题的手段。