ACM题目:连阴雨
要求
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
因为连续的降雨,我们学校操场上出现了许多水坑,现在需要统计一共有多少个水坑。
题目输入为一个N譓 (1 <= N <= 100; 1 <= M <= 100)的图,(‘W’) 代表积水,(‘.’)代表干燥。
一处积水我们认为和它周围的八个方向相邻,相邻的积水构成一个水坑。
需要输出一个数字,表示一共有多少个互不相邻的水坑。
输入
第一行:两个正整数n和m。
第二行到第n+1行:输入操场信息,每一点的状态只可能是’W’ 或者’.’。
输出
输出一个正整数,表示不相邻的水坑的数目。
输入样例
10 12
W……..WW.
.WWW…..WWW
….WW…WW.
………WW.
………W..
..W……W..
.W.W…..WW.
W.W.W…..W.
.W.W……W.
..W…….W.
输出样例
3
思路
本题是深度优先搜索应用的一道题,属于最大联通块问题。
首先建立对应的n行m列的二维数组来存储对应的水坑,再建立与之相同大小的二维数组,用来保存数组的访问信息。
接下来遍历二维数组,当当前位置的元素未被访问并且其值为W时,将当前位置标记为已经访问过了。接着使用深度优先遍历搜索以当前点为中心的八个位置,当这八个位置里有满足未被访问的元素并且值为W的,使用深度优先遍历该节点的八个位置。这样递归下去,就会将一个水坑的所有元素都便利到,这样的一次深度遍历会找到一个水坑,进行几次深度遍历就会得到几个水坑。所以,水坑的次数和深度搜索的次数保持一致。
这样,便可以通过编程来解决这道问题。
java代码
public class Question17 {
// 全局变量,保存输入的数据
static int m,n;
static char a[][];
static int vis[][];
// 水坑计数
static int number = 0;
public static void main(String[] args) {
// 获取用户的输入
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
// 输入的信息数组
a = new char[n][m];
// 访问信息数组,vis[i][j] = 0表示未被访问
vis = new int[n][m];
// 接收输入的数组,并将访问数组初始化
for(int i= 0;i<n;i++) {
String str = scanner.next();
for(int j=0;j<m;j++) {
a[i][j] = str.charAt(j);
vis[i][j] = 0;
}
}
// 关闭输入流
scanner.close();
// 对水坑的数据进行判断
for(int i= 0;i<n;i++) {
for(int j=0;j<m;j++) {
// 假如当前ij对应的vis数组值为0表示未被访问且a数组的值为W则进行一次深度优先遍历,计数值加一
if(vis[i][j]==0&&a[i][j]=='W') {
dnf(i,j);
number++;
}
}
}
// 输出结果
System.out.println(number);
}
/**
* 深度优先遍历
* @param a
* @param vis
* @param i
* @param j
*/
private static void dnf(int i, int j) {
// TODO Auto-generated method stub
vis[i][j]=1;
// 对周围八个点进行判断
for(int x=-1;x<=1;x++) {
for(int y=-1;y<=1;y++) {
// 首先该点不超过数组的最小最大边界,并且该数组未被访问过,且该位置的a数组为w
if(0<=(i+x)&&(i+x)<n&&0<=(j+y)&&(j+y)<m&&vis[i+x][j+y]==0&&a[i+x][j+y]=='W') {
dnf(i+x,j+y);
}
}
}
}
}