Java实现图的DFS应用之连通检测

题目还有分析过程都在注释里了

public class LianTongCheck {

	/*
	 * 给定一个方阵,定义连通;上下左右相邻,并且值相同
	 * 可以想象成一张地图,不同的区域被涂上不同颜色
	 * 输入:
	 * 整数N,(N<50)表示矩阵的行列数
	 * 接下来N行,每行N个字符,代表方阵中的元素
	 * 接下来一个整数M,(M<1000)表示询问数
	 * 接下来M行,每行代表一个询问
	 * 格式为4个整数,y1,x1,y2,x2
	 * 表示询问(第y1行,第x1列)与(第y2行,第x2列)是否连通
	 * 连通输出true,否则false
	 * 
	 * 例如输入
	 * 10
		0010000000
		0011100000
		0000111110
		0001100010
		1111010010
		0000010010
		0000010011
		0111111000
		0000010000
		0000000000
		3
		0 0 9 9
		0 2 6 8
		4 4 4 6
		
		输出
		false
		true
		true
	 *
	 * */
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int N=sc.nextInt();
		sc.nextLine();
		//生成方阵
		char[][] graph=new char[N][N];
		for(int i=0;i<N;i++)
				graph[i]=sc.nextLine().toCharArray();
		int M=sc.nextInt();
		//询问
		int[][] request=new int[M][4];
		for(int i=0;i<M;i++)
			for(int j=0;j<4;j++)
				request[i][j]=sc.nextInt();
		//M对起点和终点
		for(int i=0;i<M;i++)
		{	//对每个起点和终点,检查是否连通
			boolean ok=check(graph,new int[N][N],request[i]);
		    System.out.println(ok);
		}
	}
	
/**
 * 检查连个坐标是否连通
 * @param graph 方阵
 * @param label 标记方阵中的每个元素是否被访问过
 * @param points 起点和终点的坐标 x1 y1 x2 y2
 * @return
 */
	private static boolean check(char[][] graph, int[][] label, int[] points) {
		int x1=points[0];
		int y1=points[1];
		int x2=points[2];
		int y2=points[3];
		//递归的显性退出条件,起点和终点重合
		if(x1==x2&&y1==y2)
			return true;
		int value=graph[x1][y1];
		//四个方向的寻找结果,隐性退出条件
		//如果的哥方向都走不了,证明走到了死角
		boolean f1=false;
		boolean f2=false;
		boolean f3=false;
		boolean f4=false;
		
		/**
		 * 遵循以下访问顺序:左--右--上--下
		 * 
		 * 
		 * 不管是在那个方向,能探索下一步的条件都是这三个
		 * 1)下一步没有越界
		 * 2)下一步和这一步同色(值相同)
		 * 3)下一步没有被访问过
		 */
		
		//往左走
		if(x1-1>=0&&label[x1-1][y1]==0&&graph[x1-1][y1]==value)
		{
			label[x1-1][y1]=1;//把左边的点标记为已访问
			points[0]=x1-1;//把左边的点标记为新的点,递归
			f1=check(graph,label,points);
			//回溯,必须重置标记位
			label[x1-1][y1]=0;
			points[0]=x1;			
		}
		
		//往右走
		if(x1+1<graph.length&&label[x1+1][y1]==0&&graph[x1+1][y1]==value)
		{
			label[x1+1][y1]=1;
			points[0]=x1+1;
			f2=check(graph,label,points);
			//回溯,必须重置标记位
			label[x1+1][y1]=0;
			points[0]=x1;			
		}
		
		//往上走
		if(y1-1>=0&&label[x1][y1-1]==0&&graph[x1][y1-1]==value)
		{
			label[x1][y1-1]=1;
			points[1]=y1-1;
			f3=check(graph,label,points);
			//回溯,必须重置标记位
			label[x1][y1-1]=0;
			points[1]=y1;			
		}
	
		//往下走
		if(y1+1<graph.length&&label[x1][y1+1]==0&&graph[x1][y1+1]==value)
		{
			label[x1][y1+1]=1;
			points[1]=y1+1;
			f4=check(graph,label,points);
			//回溯,必须重置标记位
			label[x1][y1+1]=0;
			points[1]=y1;			
		}
		
		//有任意一个方向成功找到,即为成功
		return f1||f2||f3||f4;
	}
	
	
}

发布了24 篇原创文章 · 获赞 10 · 访问量 1288

猜你喜欢

转载自blog.csdn.net/qq_41625102/article/details/104477728