# LCP 13. 寻宝

1 <= maze.length <= 100
1 <= maze[i].length <= 100
maze[i].length == maze[j].length
S 和 T 有且只有一个
0 <= M的数量 <= 16
0 <= O的数量 <= 40，题目保证当迷宫中存在 M 时，一定存在至少一个 O 。

bfs + 状压dp.

## 代码

class Solution {
private static final int[] moveX = {-1, 1, 0, 0}, moveY = {0, 0, -1, 1};

/**
* Calculate distances between all position pairs.
* Position (x, y) is represented by (x * n + y) in a (m, n) maze.
*/
private int[] bfs(String[] maze, int start, int m, int n) {
int[] ret = new int[m * n];
Arrays.fill(ret, -1);
ret[start] = 0;
while (!queue.isEmpty()) {
for (int move=0; move<4; ++move) {
if (tx >=0 && tx < m && ty >= 0 && ty < n) {
int target = tx * n + ty;
if (ret[target] == -1 && maze[tx].charAt(ty) != '#') {
}
}
}
}
return ret;
}

public int minimalSteps(String[] maze) {
int m = maze.length, n = maze[0].length(), start = 0, end = 0, i = 0, j = 0;
ArrayList<Integer> mArr = new ArrayList<>(), oArr = new ArrayList<>();
for (i=0; i<m; ++i) {
for (j=0; j<n; ++j) {
char ch = maze[i].charAt(j);
int pos = i * n + j;
if (ch == 'S') {
start = pos;
} else if (ch == 'T') {
end = pos;
} else if (ch == 'M') {
} else if (ch == 'O') {
}
}
}
int[] startDis = bfs(maze, start, m, n);
int numM = mArr.size(), numO = oArr.size();
if (numM == 0) {
return startDis[end];
}
int[] endDis = bfs(maze, end, m, n);
int[] emDis = new int[numM], smDis = new int[numM];
for (i=0; i<numM; ++i) {
emDis[i] = endDis[mArr.get(i)] > 0? endDis[mArr.get(i)]: Integer.MAX_VALUE;
}
int[][] mAllDis = new int[numM][m * n];
for (i=0; i<numM; ++i) {
mAllDis[i] = bfs(maze, mArr.get(i), m, n);
}
for (i=0; i<numM; ++i) {
smDis[i] = Integer.MAX_VALUE;
for (int o: oArr) {
if (startDis[o] > 0 && mAllDis[i][o] > 0) {
smDis[i] = Math.min(startDis[o] + mAllDis[i][o], smDis[i]);
}
}
}
int[][] mmDis = new int[numM][numM];
for (i=0; i<numM; ++i) {
for (j=0; j<numM; ++j) {
mmDis[i][j] = Integer.MAX_VALUE;
for (int o: oArr) {
if (mAllDis[i][o] > 0 && mAllDis[j][o] > 0) {
mmDis[i][j] = Math.min(mAllDis[i][o] + mAllDis[j][o], mmDis[i][j]);
}
}
}
}
int numState = 1 << numM;
int[][] dp = new int[numState][numM];
for (i=0; i<numM; ++i) {
dp[1<<i][i] = smDis[i];
}
for (int s = 1; s < numState; ++s) {
for (i=0; i<numM; ++i) {
int ss = s - (1 << i);
if ((s & (1 << i)) != 0 && s != (1 << i)) {
dp[s][i] = Integer.MAX_VALUE;
for (j=0; j<numM; ++j) {
if (i != j && (s & (1 << j)) != 0 && mmDis[i][j] < Integer.MAX_VALUE && dp[ss][j] < Integer.MAX_VALUE) {
dp[s][i] = Math.min(dp[ss][j] + mmDis[i][j], dp[s][i]);
}
}
}
}
}
int ret = Integer.MAX_VALUE;
for (i=0; i<numM; ++i) {
if (dp[numState-1][i] < Integer.MAX_VALUE && emDis[i] < Integer.MAX_VALUE) {
ret = Math.min(dp[numState-1][i] + emDis[i], ret);
}
}
return ret < Integer.MAX_VALUE? ret: -1;
}
}

04-21 5629

01-24 2539
07-29 388
07-29 21