关于dfs:
例题:计算细胞数量
可以用递归实现,也可以不用递归实现(队列)
一矩形阵列由数字 00 到 99 组成,数字 11 到 99 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
输入格式
第一行两个整数代表矩阵大小 nn 和 mm。
接下来 nn 行,每行一个长度为 mm 的只含字符 0 到 9 的字符串,代表这个 n imes mn×m 的矩阵。
输出格式
一行一个整数代表细胞个数。
输入输出样例
输入 #1复制
4 10
0234500067
1034560500
2045600671
0000000089
输出 #1复制
4
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 1 le n,m le 1001≤n,m≤100。
题解:灌水法求细胞数
基本思路:遍历一遍给定的二维数组:从每个非零的单元出发,灌水把上下左右方向的单元置零,然后细胞数量+1
不过这里是利用了方向数组进行dfs(就是一种深度搜索)
#include <iostream>
#include <cstdio>
using namespace std;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int ans[100][100];
int s=0;
int n,m;
void dfs(int x,int y)
{
ans[x][y]=0;//先置零
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(0<=nx && nx<n && 0<=ny && ny<m && ans[nx][ny]!=0)
dfs(nx,ny);
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cin>>ans[i][j];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(ans[i][j]!=0)
{
s++;
dfs(i,j);
}
}
}
cout<<s;
return 0;
}
犯错的一个问题:
论“定向灌水法”的不可行性
//定向漫水法——只从对角线出发,或者只从横向/竖向出发
该方法处理dfs问题(例如数细胞数量是不可行的)
原因如下:
- 漫水法是针对每一个单元来的,从一个基准单元蔓延到周围单元以后,周围单元还会继续按照这种方式蔓延下去(因为是递归)。所以,如果是自由蔓延,也即没有方向的限制的话(有障碍限制),是可行的。但是一旦按方向去灌水,比如左右或者上下,或者对角线方向,这个方法就不再成立了,因为此时如果不加条件&&ans[nx][ny]!=1的话,递归就结束不了(会一直左右/上下地去灌水),加了就又会导致不同方向的漫水会互相影响使得有些本该被漫水的地方没被处理。
- 除非用一种方法解决这个问题:那就是每次不同方向的漫水都放在一个初始的新数组里,然后不同方向漫水完成以后,把这些结果整合在一起就行。(比较麻烦)
- 所以k皇后问题不能用dfs里的灌水法。