求下列情况距离的最小值(如果合法)
S不经过D直接走到E bfs(S,E)
S先拿钥匙 bfs(S,E) 再从钥匙处走到E bfs(K,E)
bfs最好复用。
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
public static int H, W, S, E, K, D;
public static char[][] mg;
public static int[] dis;
public static boolean[] v;
public static boolean key = false;
public static int[][] dir = {{-1,0},{1,0},{0,-1},{0,1}};
public static boolean bfs(int s, int t) {//s为起点,t为终点
Queue<Integer> q = new LinkedList<>();
q.add(s);
//这里不用dis[s] = 0 可以接上次bfs一直累加
v[s] = true;
while(!q.isEmpty()) {
int tmp = q.poll();
int x = tmp / W, y = tmp % W;
for(int i = 0; i < 4; ++i) {
int nx = x + dir[i][0], ny = y + dir[i][1], pos = nx * W + ny;
//1、四周是墙壁无需判断越界 2、如果下个方向D但起点不是K,视为墙壁
if(mg[nx][ny] == 'W' || v[pos] || mg[nx][ny] == 'D' && s != K) continue;
dis[pos] = dis[tmp] + 1;
v[pos] = true;
if(pos == t) return true;
q.add(pos);
}
}
return false;
}
public static void main(String[] args) {
InputReader in = new InputReader();
PrintWriter out = new PrintWriter(System.out);
H = in.nextInt();
W = in.nextInt();
mg = new char[H][W];
dis = new int[H * W];
v = new boolean[H * W];
for(int i = 0; i < H; ++i) {
char[] chs = in.next().toCharArray();
for(int j = 0; j < W; ++j) {
mg[i][j] = chs[j];
if(mg[i][j] == 'S') S = i * W + j;
if(mg[i][j] == 'E') E = i * W + j;
if(mg[i][j] == 'K') K = i * W + j;
}
}
int ans = Integer.MAX_VALUE;//假设距离无限远
if(bfs(S, E)) ans = dis[E];//不经过D直接走到E
for(int i = 0, l = H * W; i < l; ++i) v[i] = false;//每次bfs前都要把标记清除掉
if(bfs(S, K)) {//能拿到钥匙
for(int i = 0, l = H * W; i < l; ++i) v[i] = false;
if(bfs(K, E)) ans = Math.min(ans, dis[E]);//取二者最小值
}
out.println(ans == Integer.MAX_VALUE ? -1 : ans);
out.close();
}
}
class InputReader{BufferedReader buf;StringTokenizer tok;InputReader(){buf = new BufferedReader(new InputStreamReader(System.in));}boolean hasNext(){while (tok == null || !tok.hasMoreElements()){try{tok = new StringTokenizer(buf.readLine());}catch (Exception e){return false;}}return true;}String next(){if (hasNext())
return tok.nextToken();return null;}int nextInt(){return Integer.parseInt(next());}long nextLong(){return Long.parseLong(next());}double nextDouble(){return Double.parseDouble(next());}BigInteger nextBigInteger(){return new BigInteger(next());}BigDecimal nextBigDecimal(){return new BigDecimal(next());}}