leetcode 864. 获取所有钥匙的最短路径(BFS,状态压缩)
阅读原文时间:2023年07月09日阅读:1

题目链接

864. 获取所有钥匙的最短路径

题意

给定起点,要求在最短步骤内收集完所有钥匙,遇到每把锁之前只有 有对应的钥匙才能够打开

思路

BFS+状态压缩典型题目

先确定起点和总的钥匙数目,其次难点有两处:

  • 如何确定当前路径下已经收集好特定的钥匙
  • 如何确定钥匙已经全部收集完成

第一个问题:可以把每一个节点的状态定义为(x,y,state),其中state为钥匙数目的二进制表示,例如现在收集'b'这把钥匙,那么state更新为2(000010),括号里面为钥匙的二进制数,如果下一轮遇到'B',只需要检查state里面的倒数第二位是否已经更新即可

第二个问题:钥匙全部收集好的话,那么statey应该为(1<<cnt)-1,其中cnt为总的钥匙数量,比如有6把钥匙,全部收集满的状态为2^6-1(111111),括号里面为钥匙的二进制数

class Solution {
public:
    //怎么记录更新之后的连续状态呢
    //需要学习的是并非整个路径的状态 ,而是需要记录到某个节点的状态[x][y][state]

    //1. 有时候可能需要走回头路? 那标记的时候除了位置,再把状态也给标记上
    //2. 怎么判断钥匙已经全部取完? (1<<max_len-1) 全部标记
    struct Node{
        int x,y,state;
        Node(int x0,int y0,int state0){
            x=x0;y=y0;state=state0;
        }
    };
    int dx[4]={1,-1,0,0};
    int dy[4]={0,0,1,-1};
    // unordered_set<Node> st;
    int st[31][31][129];
    queue<Node> Q;

    int shortestPathAllKeys(vector<string>& grid) {
        memset(st,0,sizeof(st));

        if(grid.empty()) return 0;
        int n=grid.size();
        int m=grid[0].size();//n行m列

        int cnt=0,nx=-1,ny=-1;//钥匙数量,初始值的位置
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(grid[i][j]=='@') {nx=i;ny=j;}
                else if(grid[i][j]>='a' &&grid[i][j]<='z') cnt++;
            }
        }
        Q.push(Node{nx,ny,0});
        st[nx][ny][0]=1;

        int step=0;//移动次数
        while(!Q.empty()){
            int len=Q.size();//这一层的节点数
            // if(cnt<=0) break;
            for(int i=0;i<len;i++){
                Node cur=Q.front();
                Q.pop();
                if(cur.state==(1<<cnt)-1) return step;
                for(int k=0;k<4;k++){
                    int tmpx=cur.x+dx[k];
                    int tmpy=cur.y+dy[k];
                    int nState=cur.state;

                    if(tmpx <0 || tmpx >n-1 || tmpy<0 || tmpy>m-1) continue;//0~n-1 这里不是n 而是大于n-1.......

                    if(grid[tmpx][tmpy]=='#') continue;
                    if(grid[tmpx][tmpy]>='a' && grid[tmpx][tmpy]<='z'){
                        nState=cur.state|(1<<(grid[tmpx][tmpy]-'a'));
                    }

                    if(grid[tmpx][tmpy]>='A' && grid[tmpx][tmpy]<='Z'){
                        // printf("%d %d\n",nState,nState & (1<<(grid[tmpx][tmpy]-'A')));
                        if((nState & (1<<(grid[tmpx][tmpy]-'A')))==0){
                            continue;
                        }
                    }

                    //表示已经访问过 加上状态
                    if(!st[tmpx][tmpy][nState]){
                        st[tmpx][tmpy][nState]=1;
                        Q.push(Node{tmpx,tmpy,nState});
                    }
                }
            }
            step++;
        }
        return -1;
    }
};

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章