LCP 13. 寻宝

link

class Solution {
public:
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    struct Point{
        int x;
        int y;
    };
    int dis[105][105];
    int m,n;
    Point S,T;
    int mcnt;
    int ocnt;
    vector<vector<int>> dp;
    int minimalSteps(vector<string>& maze) {
        vector<Point> ms;
        vector<Point> os;
        m=maze.size();
        n=maze[0].size();
        
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(maze[i][j]=='M'){
                    ms.push_back(Point{i,j});
                    mcnt++;
                }else if(maze[i][j]=='O'){
                    os.push_back(Point{i,j});
                    ocnt++;
                }else if(maze[i][j]=='S'){
                    S=Point{i,j};
                }else if(maze[i][j]=='T'){
                    T=Point{i,j};
                }
            }
        }
        vector<int> StoStone(ocnt,-1);                   // S to stone
        int StoT=-1;
        bfs(S,maze);
        StoT=dis[T.x][T.y];
        for(int i=0;i<ocnt;i++){
            StoStone[i]=dis[os[i].x][os[i].y];
        }
        if(mcnt==0){
            return StoT;
        }

        vector<int> TtoM(mcnt,-1);                     // T to M
        bfs(T,maze);
        for(int i=0;i<mcnt;i++){
            TtoM[i]=dis[ms[i].x][ms[i].y];
        }

        vector<vector<int>> MtoStone(mcnt,vector<int>(ocnt,-1));      // M to stone
        for(int i=0;i<mcnt;i++){
            bfs(ms[i],maze);
            for(int j=0;j<ocnt;j++){
                MtoStone[i][j]=dis[os[j].x][os[j].y];
            }
        }

        vector<vector<int>> MtoM(mcnt,vector<int>(mcnt,-1));           //M to M
        for(int i=0;i<mcnt;i++){
            for(int j=i+1;j<mcnt;j++){
                for(int k=0;k<ocnt;k++){
                    if(MtoStone[i][k]==-1 || MtoStone[j][k]==-1) continue;
                    if(MtoM[i][j]==-1) MtoM[i][j]=MtoStone[i][k]+MtoStone[j][k];
                    else if(MtoStone[i][k]+MtoStone[j][k]<MtoM[i][j]) MtoM[i][j]=MtoStone[i][k]+MtoStone[j][k];
                }
                MtoM[j][i]=MtoM[i][j];
            }
        }

        vector<int> StoM(mcnt,-1);                      // S to M
        for(int i=0;i<mcnt;i++){
            for(int j=0;j<ocnt;j++){
                if(StoStone[j]==-1 || MtoStone[i][j]==-1) continue;
                if(StoM[i]==-1) StoM[i]=StoStone[j]+MtoStone[i][j];
                else if(StoStone[j]+MtoStone[i][j]<StoM[i]) StoM[i]=StoStone[j]+MtoStone[i][j];
            }
        }

        int all=(1<<mcnt)-1;
        dp=vector<vector<int>>(mcnt,vector<int>(all,-2));
        int res=INT_MAX;
        
        for(int i=0;i<mcnt;i++){
            int tmp=StoM[i];
            if(tmp==-1) continue;
            int next=dfs(i,all^(1<<i),TtoM,MtoM);
            if(next!=-1){
                res=min(res,tmp+next);
            }
        }

        return res==INT_MAX?-1:res;
    }

    int dfs(int cur, int state, vector<int> &TtoM,vector<vector<int>>& MtoM){
        if(state==0){
            return TtoM[cur];
        }
        if(dp[cur][state]!=-2) return dp[cur][state];
        int ret=-1;
        for(int i=0;i<mcnt;i++){
            if((state&(1<<i))==0 || MtoM[cur][i]==-1) continue;
            int tmp=MtoM[cur][i];
            int next=dfs(i,state^(1<<i),TtoM,MtoM);
            if(next==-1) continue;
            if(ret==-1) ret=tmp+next;
            else ret=min(ret,tmp+next);
        }
        return dp[cur][state]= ret;
    }

    void bfs(Point start, vector<string>& maze){
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                dis[i][j]=-1;
            }
        }
        dis[start.x][start.y]=0;
        queue<Point> q;
        q.push(start);
        vector<vector<int>> visited(m,vector<int>(n));
        visited[start.x][start.y]=1;
        while(!q.empty()){
            auto cur=q.front();
            q.pop();
            for(int d=0;d<4;d++){
                int nx=cur.x+dir[d][0];
                int ny=cur.y+dir[d][1];
                if(nx<0 || nx>=m || ny<0 || ny>=n || maze[nx][ny]=='#' || visited[nx][ny]==1) continue;
                visited[nx][ny]=1;
                dis[nx][ny]=1+dis[cur.x][cur.y];
                q.push(Point{nx,ny});
            }
        }
    }
};
原文地址:https://www.cnblogs.com/FEIIEF/p/12775783.html