poj2386 水坑(dfs求连通子图数)

题意:有一个大小为N×M的园子,雨后积起了水。八连通的积水被认为是连在一起的。求园子里一共有多少水洼?


  • W* (八连通指的就是左图中相对W的*的部分)

Sample Input

10 12
W…WW.
.WWW…WWW
…WW…WW.
…WW.
…W…
…W…W…
.W.W…WW.
W.W.W…W.
.W.W…W.
…W…W.
Sample Output

3

import java.util.*;

public class Main{
	public static int maxn = 1000;
	public static int[][] flag = new int[maxn+10][maxn+10];
	public static int[][] dir = {{1,0},{0,1},{-1,0},{0,-1},{1,1},{-1,1},{-1,-1},{1,-1}};
	public static int[][] mapp = new int[maxn+10][maxn+10];
	public static int n,m,cnt=0;
	public static String[] str = new String[maxn+10];
	public static void dfs(int x,int y){
		flag[x][y]=1;
		for(int i=0;i<8;i++){
			int dx = x + dir[i][0];
			int dy = y + dir[i][1];
			if(dx>=0&&dx<=n-1&&dy>=0&&dy<=m-1&&str[dx].charAt(dy)=='W'){
			if(flag[dx][dy]==0){
				dfs(dx,dy);
			}
		}
	}
}
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		m = scanner.nextInt();
		for(int i=0;i<n;i++){
			str[i] = scanner.next();
		//	System.out.println(str[i]);
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				flag[i][j] = 0;
			}
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(str[i].charAt(j)=='W'&&flag[i][j]==0){
					dfs(i,j);
					cnt++;
				}
			}
		}
		System.out.println(cnt);
	}
	
}
/*
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
*/

笔记:
1.连通子图就是dfs结束了多少次
2.思路:遍历整张图,遇到字符为’W’并且未访问过就 dfs 这个坐标,dfs多少次就是多少个连通子图(水坑)。dfs思路:每次先把当前’W’节点设置为访问过,然后遍历所有的邻接节点,如果邻接节点在范围内,值为’W’,并且未访问过,就继续dfs这个节点。
3.设置二维数组并初始化:

int[][] dir = {{},{},{}};
public static int[][] dir = {{1,0},{0,1},{-1,0},{0,-1},{1,1},{-1,1},{-1,-1},{1,-1}};

4.String 类型字符串str取得下标值用str.charAt(i)不是str[i],二维string则用str[i].charAt(j)取得下标所对应值。string 一般用 next() 输入不会保存空格,用nextLine()输入保存空格。定义一维string 用

String[] str = new String[maxn+10];

一维String等价于二维char,
定义就是定义一维字符串String[] str = new String[maxn+10];
输入就是输入n条字符串 for(int i=0;i 取值就是取出第 i 条字符串的下标为 j 的值,str[i].charAt(j)
5.java中二维字符数组就当成一维String来处理,用char的话输入还要用string输入再赋值麻烦。一维string就三个问题,定义,输入,取值。:

//定义
 String[] str = new String[maxn+10];
 //输入
 for(int i=0;i<n;i++){
 str[i] = scanner.next();
 }
 //取值
str[i].charAt(j);

6.java中定义数组默认为初始化为 0 。在main里和main外都是初始化为0.
7.java中类似memset的方法为Arrays.fiil(a,value)
而且可以初始化为任意值,int数组可以,String也可以,初始化为任意值。

import java.util.*;

public class Main{
	public static int[] a =new int[10] ;
	public static String[] str = new String[10];
	public static void main(String[] args){
		
		Arrays.fill(str,"abcd");
		Arrays.fill(a,-1);
		for(int i=0;i<10;i++){
			System.out.println(str[i]);
		}
		for(int i=0;i<10;i++){
			System.out.println(a[i]);
		}
	}
}

你可能感兴趣的:(算法竞赛)