【搜索】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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章