LCP 13 bfs + 状态压缩 dp

题意

传送门 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;
    }
};

你可能感兴趣的:(dfs,&,bfs,dp)