[検索] C035_oenj_レスキュー作戦(PQ /ナイーブ)

1.問題

王女は邪悪な者に捕らえられ、独房のどこかに抱かれていました。セルは、N * M(N、M <= 200)の行列で表されます。マトリックスの各項目は、道路(@)、壁(#)、および警備員(x)を表すことができます。

英雄的な騎士(r)が王女を一人で救うことにしました(a)。救助成功の表現は「騎士がお姫様の位置に着いた」と表現します。

王女のいる場所への道で警備員が遭遇する可能性があるため、騎士が警備員に会ったら、次に進むには警備員を殺さなければなりません。

今度は、騎士が上下左右に移動できると仮定します。ポジションの移動ごとに1単位時間、ガードを倒すには追加の単位時間が必要です。また、騎士はすべての警備員を殺すのに十分強いと仮定します。

セルマトリックス、マトリックス内のプリンセス、ナイト、ガードの位置を考慮して、レスキュー操作が成功するのにかかる最小時間を計算してください。

入力

1行目は整数Sで、入力データのグループ(複数の入力グループ)の数を示します。次に、S個のデータセットがあり、各データセットは次の形式で入力されます。

  1. 2つの整数はNとMを表します(N、M <= 200)。
  2. 次に、各行にM文字のN行があります。「@」は道路を表し、「a」は姫を表し、「r」は騎士を表し、「x」は警備員を表し、「#」は壁を表します。

アウトプット

レスキュー操作が成功すると、操作の最短時間を示す整数が出力されます。
成功しない場合は「不可能」を出力

样例输入
2
7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@ 
13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@

样例输出
13
7

二、Solution

方法1:bfs

元のアイデア: bfsのステップの昇順でノードの優先度キューを使用しますが、問題があります:騎士のいない道路が騎士よりもコストが高い場合、アルゴリズムは間違っています。

修正案:ステップが重ねられているので優先キューを使うのが正しい...

import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static int R, C;
	static char[][] grid;
	final static int[][] dir = { {1,0},{0,-1},{0,1},{-1,0} };
	static int sx, sy, ex, ey;
	
	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));
		int S = sc.nextInt();
		while (S-- > 0) {
			R = sc.nextInt();
			C = sc.nextInt();
			grid = new char[R][C];
			for (int i = 0; i < R; i++) {
				String s = sc.next();
				for (int j = 0; j < C; j++) {
					grid[i][j] = s.charAt(j);
					if (grid[i][j] == 'a') 		ex = i; ey = j;
					else if (grid[i][j] == 'r') sx = i; sy = j;
				}
			}
			int res = bfs();
			System.out.println(res == -1 ? "Impossible" : res);
		}
    }
	private static int bfs() {
		Queue<Pos> q= new PriorityQueue<>((e1, e2) -> e1.step - e2.step);
		q.add(new Pos(sx, sy, 0));
        grid[sx][sy] = '#';		
		while (!q.isEmpty()) {
			Pos cur = q.poll();
			if (cur.x == ex && cur.y == ey)
				return cur.step;
				
			for (int k = 0; k < 4; k++) {
				int tx = cur.x + dir[k][0];
				int ty = cur.y + dir[k][1];
				if (!inArea(tx, ty) || grid[tx][ty] == '#')
					continue;
				if (grid[tx][ty] == 'x') {
					q.add(new Pos(tx, ty, cur.step+2));
				} else {
					q.add(new Pos(tx, ty, cur.step+1));
				}
				grid[tx][ty] = '#';
			}
		}
		return -1;
	}
	static class Pos {
		int x, y, step;
		public Pos(int _x, int _y, int _step) {
		   x = _x;
		   y = _y;
		   step = _step;
		}
	}
}	

複雑さの分析

  • 時間の複雑さ: R × C O(R×C)
  • スペースの複雑さ: (...)

方法2:ナイーブbfs

  • 各@間のエッジの重みは1、@とx間のエッジの重みは2です。
  • dist[ex][ey] 何度も通るかもしれませんが、私は最小のものしか取りません。
  • この場合、完全に網羅されていないため、通過していないポイントをマークすることはできません。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main {
	static int R, C;
	static char[][] grid;
	final static int[][] dir = { {1,0},{0,-1},{0,1},{-1,0} };
	static int sx, sy, ex, ey;
	static int[][] dist;
	static int INF = 0x3f3f3f3f;
	
	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 S = sc.nextInt();
		while (S-- > 0) {
			R = sc.nextInt();
			C = sc.nextInt();
			grid = new char[R][C];
			dist = new int[R][C];
			for (int i = 0; i < R; i++) {
				String s = sc.next();
				for (int j = 0; j < C; j++) {
					dist[i][j] = INF;
					grid[i][j] = s.charAt(j);
					if (grid[i][j] == 'a') {
						ex = i; ey = j;
					} else if (grid[i][j] == 'r') {
						sx = i; sy = j;
					} 
				}
			}
			bfs();
			System.out.println(dist[ex][ey] == INF ? "Impossible" : dist[ex][ey]);
		}
    }
	private static void bfs() {
		Queue<Pos> q= new ArrayDeque<>();
		q.add(new Pos(sx, sy));
		dist[sx][sy] = 0;
		while (!q.isEmpty()) {
			Pos cur = q.poll();
			for (int k = 0; k < 4; k++) {
				int tx = cur.x + dir[k][0];
				int ty = cur.y + dir[k][1];
				if (!inArea(tx, ty) || grid[tx][ty] == '#')
					continue;
				int t = dist[cur.x][cur.y] + 1;
				if (grid[tx][ty] == 'x')
					t++;
				if (dist[tx][ty] > t) {
					dist[tx][ty] = t;
					q.add(new Pos(tx, ty));
				}
			}
		}
	}
	static class Pos {
		int x, y;
		public Pos(int _x, int _y) {
		   x = _x;
		   y = _y;
		}
	}
}	

複雑さの分析

  • 時間の複雑さ: O()
  • スペースの複雑さ: O()
元の記事714件を公開 賞賛された199件 50,000件以上の表示

おすすめ

転載: blog.csdn.net/qq_43539599/article/details/105646238