题意
传送门 LCP 13.寻宝
题解
bfs 求各机关点到地图各点的最短距离;遍历石碓求各机关点间经过石碓的最短距离;对经过的机关点状态压缩,记忆化搜索求解。
class Solution {
private:
int INF = 0x3f3f3f3f;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
int H, W, sX, sY, tX, tY, si, ti;
int dis[20][105][105];
int diso[20][20];
vector<int> oX, oY, mX, mY;
int dp[1 << 16][16];
void bfs(int x, int y, vector<string>& maze, int dis[105][105]){
dis[x][y] = 0;
queue<int> qx, qy;
qx.push(x); qy.push(y);
while(!qx.empty()){
int x = qx.front(); qx.pop();
int y = qy.front(); qy.pop();
for(int i = 0; i < 4; i++){
int nx = x + dx[i], ny = y + dy[i];
if(nx >= 0 && nx < H && ny >= 0 && ny < W && maze[nx][ny] != '#' && dis[nx][ny] == INF){
dis[nx][ny] = dis[x][y] + 1;
qx.push(nx); qy.push(ny);
}
}
}
}
// 状态压缩 dp
int rec(int S, int u){
if(S == (1 << mX.size()) - 1){
return dp[S][u] = dis[ti][mX[u]][mY[u]];
}
if(dp[S][u] != -1) return dp[S][u];
int res = INF;
for(int i = 0; i < mX.size(); i++){
if(!((S >> i) & 1)){
res = min(res, diso[i][u] + rec(S | (1 << i), i));
}
}
return dp[S][u] = res;
}
public:
int minimalSteps(vector<string>& maze) {
H = maze.size(), W = maze[0].length();
oX.clear(); oY.clear(); mX.clear(); mY.clear();
for(int i = 0; i < H; i++){
for(int j = 0; j < W; j++){
if(maze[i][j] == 'S') sX = i, sY = j;
else if(maze[i][j] == 'T') tX = i, tY = j;
else if(maze[i][j] == 'O'){
oX.push_back(i); oY.push_back(j);
}
else if(maze[i][j] == 'M'){
mX.push_back(i); mY.push_back(j);
}
}
}
memset(dis, 0x3f, sizeof(dis));
for(int i = 0; i < mX.size(); i++){
bfs(mX[i], mY[i], maze, dis[i]);
}
si = mX.size(), ti = si + 1;
bfs(sX, sY, maze, dis[si]); bfs(tX, tY, maze, dis[ti]);
if(mX.size() == 0) return dis[si][tX][tY] >= INF ? -1 : dis[si][tX][tY];
// 求 "O" 间经过 "M" 的最短距离
for(int i = 0; i < mX.size(); i++){
for(int j = i + 1; j < mX.size(); j++){
int mincost = INF;
for(int k = 0; k < oX.size(); k++){
mincost = min(mincost, dis[i][oX[k]][oY[k]] + dis[j][oX[k]][oY[k]]);
}
diso[i][j] = diso[j][i] = mincost;
}
}
int res = INF;
memset(dp, -1, sizeof(dp));
for(int i = 0; i < mX.size(); i++){
int mincost= INF;
for(int j = 0; j < oX.size(); j++){
mincost = min(mincost, dis[si][oX[j]][oY[j]] + dis[i][oX[j]][oY[j]]);
}
res = min(res, rec(1 << i, i) + mincost);
}
return res >= INF ? -1 : res;
}
};