Connected block (dfs) java implementation

content

foreword  

Example link

what is a connected block

specific ideas

code

Notice


foreword  

The problem of connected blocks belongs to the depth-first traversal of dfs of graphs. This article introduces dfs to solve the problem of connected blocks through a simple case of finding the number of connected blocks.

Example link

http://oj.hzjingma.com/p/29?view=classic

The example given is a char type map, ' . ' means no access, and ' W ' means connectable, and the specific situation should be modified according to the title.

what is a connected block

As shown in the figure, the entire table is a 5*5 two-dimensional array, which is used to represent the entire map. The white fill is the subscript of the two-dimensional array. The outermost light green represents the boundary of the map (why the boundary is created below), and the darker color is a two-dimensional array for storing data, that is, the subscript (1~4)*(1~4). The block with the darkest color is the connected block, and there are three connected blocks (up, down, left and right connected, regardless of the oblique pair connection) given in the figure.

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAcXFfNTIzNjAwNjk=,size_16,color_FFFFFF,t_70,g_se,x_16

specific ideas

In addition to the number of rows and columns and the development of a two-dimensional array map, a two-dimensional array visited, which is the same size as the map, is needed to indicate whether the current node has been visited. The specific idea is similar to the dfs of the graph. When a node is traversed to 1, it means that the node can be connected (may be different according to the title) and deep traversal is performed before it has been visited.

See the code for details.

code

import java.util.Scanner;
/**
 * 注意本例题中 
 * char[][]map地图   值为' . ' 代表不通,' W '代表可以连通
 * int[][] visitied访问标记,初始值0未访问,1已访问
 * @author lenovo
 *
 */

public class Main {
	static int n,m,ans;
	static char[][] map;
	static int[][] vistied;
	static int[][] step= {
   
   {1,0},{0,1},{-1,0},{0,-1}};
	/*
	 * 上下左右移动遍历搜索
	 *  1 ,0 表示 x + 1 ,y + 0 向右移动,其他同理
	 *  如果为八向连通 则加上, { 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 } 代表斜向移动
	 */
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		map=new char[n+2][m+2];
		vistied=new int[n+2][m+2];
		//初始化地图,创建边界
		for (int i = 0; i <= n+1; i++) {
			map[i][0] = '.';
			map[i][m+1] = '.';
		}
		for (int i = 0; i <= m+1; i++) {
			map[0][i] = '.';
			map[n+1][i] = '.';
		}
		//录入数据图(1~n)*(1~m)
		for (int i = 1; i <= n; i++) {
			String s=sc.next();
			int k=0;
			for (int j = 1; j <= m; j++) {
				map[i][j]=s.charAt(k++);
			}
		}
		//从1-n 1-m一次遍历整张数据图
		for (int x = 1; x <=n; x++) {
			for (int y =1; y <=m; y++) {
				//如果当前节点为'W'可以连通 并且为被访问则说明存在一个连通块
				if(vistied[x][y] ==0 && map[x][y] == 'W') {
					ans++;//连接块数量+1
					vistied[x][y] = 1;//当前节点标记为已经访问,以免重复判断
					dfs(x,y);//进行深度优先遍历,将与其连通的所有节点都标记为已经访问。
					//遍历完后从(1,1)到下一个节点(1,2)继续遍历,一次类推,直到所有节点全遍历完。
				}
			}
		}
		System.out.println(ans);
	}
	private static void dfs(int x, int y) {
		/**
		 * step.length - 1 = 3
		 * 0 1 2 3 四步代表上下左右均走一遍
		 */
		for (int i = 0; i <=(step.length - 1); i++) {
			int newx=x+step[i][0]; //x移动
			int newy=y+step[i][1];//y移动
			//如果移动后的节点 为 'W'可连通,并且未访问,则以移动后的节点为起点继续移动
			if(map[newx][newy] =='W' && vistied[newx][newy] ==0) {
				vistied[newx][newy] = 1;//标记为已访问
				dfs( newx, newy);
			}
		}
	}
	
}

Notice

       In practical application, in order to prevent when the node is on the boundary, for example, the subscript of the node is (0,0) and the subscript of its left node is (-1,0), then -1 will cross the boundary. Therefore, the size of opening a two-dimensional array is always two more lines than the n*m ​​given in the title, that is, opening a two-dimensional array of size (n+2)*(m+2).

Guess you like

Origin blog.csdn.net/qq_52360069/article/details/123449592