【搜索】B030_逃离迷宫(bfs + 穷举方向)

一、题目描述

给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?

Input

  • 第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
  • 第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符’.‘表示该位置为空地,字符’*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。

Output

  • 每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
Sample Input
2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3

Sample Output
no
yes

二、题解

题目大意:判断能不能在限制拐弯数的情况下从起点走到终点。

方法一:bfs + 单方向穷举

  • 当枚举某一个方向时,就继续从这个方向走到底,换个方向之后也是这样。
  • 当有结点出队时,之前的 4 个方向的点肯定被标记为 visited 了,所以只能拐弯,这时把出队的结点的拐弯数 cur.turn++
import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static int R, C;
	static char[][] grid;
	final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
	static boolean[][] vis;
	
	private static boolean inArea(int x, int y) {
		return x >= 0 && x < R && y >= 0 && y < C;
	}
    // public static void main(String[] args) throws IOException {  
        // Scanner sc = new Scanner(new BufferedInputStream(System.in));
        // PrintWriter pw = new PrintWriter(System.out, true); //自动刷新
		// int T = sc.nextInt();
		// while (T-- > 0) {
		    // R = sc.nextInt();
    		// C = sc.nextInt();
    		// grid = new char[R][C];
    		// vis = new boolean[R][C];
    		
    		// for (int i = 0; i < R; i++) {
    			// grid[i] = sc.next().toCharArray();
				
    			// int limit = sc.nextInt();
				// int x1=sc.nextInt();
				// int y1=sc.nextInt();
				// int x2=sc.nextInt();
				// int y2=sc.nextInt();
				 // System.out.println(bfs(x1, y1, x2, y2, limit) ? "yes" : "no");  
    		// }
		// }
    // }
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int t=sc.nextInt();
		while(t-->0){
			R=sc.nextInt();
			C=sc.nextInt();
			grid=new char[R][C];
			vis=new boolean[R][C];
			
			for(int i=0;i<R;i++){
			    grid[i]=sc.next().toCharArray();
			}
			int limit=sc.nextInt();
			int y1=sc.nextInt();
			int x1=sc.nextInt();
			int y2=sc.nextInt();
			int x2=sc.nextInt();
			System.out.println(bfs(x1-1, y1-1, x2-1, y2-1, limit) ? "yes" : "no");  
		}
	}
	private static boolean bfs(int sx, int sy, int ex, int ey, int limit) {
		Queue<Pos> q= new LinkedList<>();
		q.add(new Pos(sx, sy, -1));
		vis[sx][sy] = true;
		
		while (!q.isEmpty()) {
			Pos cur = q.poll();
			if (cur.x == ex && cur.y == ey && cur.turn <= limit) {
				return true;
			}
			cur.turn++;
			for (int k = 0; k < 4; k++) {
				int tx = cur.x + dir[k][0];
				int ty = cur.y + dir[k][1];
				while (inArea(tx, ty) && grid[tx][ty] != '*') {
				    if (!vis[tx][ty]) {
			        	q.add(new Pos(tx, ty, cur.turn));
					    vis[tx][ty] = true;
				    }
					tx += dir[k][0];
					ty += dir[k][1];
				}
			}
		}
		return false;
	}
	static class Pos {
		int x, y, turn;
		public Pos(int _x, int _y, int _turn) {
		   x = _x;
		   y = _y;
		   turn = _turn;
		}
	}
}	

复杂度分析

  • 时间复杂度:O(R×C)O(R × C)
  • 空间复杂度:O(R×C)O(R × C)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章