DFS和BFS两种搜索方式,DFS是利用递归方式,需要一个visited数组,记录是否将节点访问过。BFS用队列来存储部分中间节点。
数据量小,而且要求简单,就用DFS。
杭电1241
DFS简单题
原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=1241
题目大意是:一个公司开采石油,在一个矩形区域,每个元素要么有油,要么没油,如果有油的地方是连接的(八个方向),就算是一片油区,问总共有多少油区。
思路:对每个元素按顺序搜索,如果该元素有油而且没搜索过,那么使用DFS来搜索周围其他地方,并标志上visited表示已经搜索过。使用DFS搜索完这个元素之后,表明这片油区的所有元素已经访问过,所以ans++,继续往下搜索。
代码如下:
写程序时遇到一个问题,用VS2013,scanf那里竟然读取不了元素,就是我在cin前边注释掉的那行,原因是scanf在读char类型时把空格和回车都算上了,而读int这样的类型的时候,会自动匹配一下,所以以后要么用cin读字符,要么就在有空格或者回车的地方读一个空的变量。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include "stdio.h"
using namespace std;
char a[100][100]; //输入信息
int visited[100][100]; //记录每个点是否被访问,1表示已经访问过
int direction[8][2] = { 1, 1, 1, 0, 1, -1, 0, -1, 0, 1, -1, -1, -1, 1, -1, 0 };
int m, n;
int ans = 0; //表示最终结果,即连通区域的个数
void dfs(int nx, int ny){
for (int i = 0; i < 8; i++){
int x = nx + direction[i][0];
int y = ny + direction[i][1];
if (x >= 0 && x < m && y >= 0 && y < n && visited[x][y] != 1 && a[x][y]=='@'){
visited[x][y] = 1;
dfs(x, y);
}
}
}
int main(){
while (true){
ans = 0;
scanf("%d %d", &m, &n);
if (m == 0 && n == 0) break;
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
//scanf("%c", &a[i][j]);
cin >> a[i][j];
}
}
memset(visited, 0, sizeof(visited));
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
if (visited[i][j] != 1 && a[i][j] == '@'){
visited[i][j] = 1;
dfs(i, j);
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}
POJ 1154
题目链接:
大意:有一个矩阵,元素是26个大写字母,从第一行第一列开始出发,每次可以往前后左右走一格,但是比如之前走过了字母’A’,以后就不能走这个字母了。问最多可以走几步。
思路:
大概意思和上面写的杭电1241差不多,只是不需要visited数组,变成了v[26]数组,然后就是简单的DFS。
#include <algorithm>
#include <cstring>
#include <iostream>
#include "stdio.h"
using namespace std;
char a[21][21];
int v[26];
int m, n;
int direction[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
int ans, temp;
void dfs(int x, int y){
for (int i = 0; i < 4; i++){
int nx = x + direction[i][0];
int ny = y + direction[i][1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && v[a[nx][ny] - 'A'] != 1){
v[a[nx][ny]-'A'] = 1;
temp++;
dfs(nx, ny);
if (ans < temp) ans = temp; //每次记录下最大值来
temp--; //别忘了还要自减,恢复原来的状态
v[a[nx][ny]-'A'] = 0;
}
}
}
int main(){
cin >> m >> n;
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
cin >> a[i][j];
}
}
ans = 1;
temp = 1;
memset(v, 0, sizeof(v));
v[a[0][0] - 'A'] = 1; //千万不要忘了开始要将出发点设置为1
dfs(0, 0);
cout << ans << endl;
return 0;
}