leetcode 1263 Minimum Moves to Move a Box to Their Target Location  (双向队列 BFS)

10 篇文章 0 订阅
1 篇文章 0 订阅

题意:

在推箱子游戏中,怎么求人物为了把箱子推到终点所需要的推箱子次数最少的次数。

解题思路:

这题的题目数据非常小,考虑用暴力搜索的方法。很自然地我们可以建立状态

flag[pr][pc][br][bc];

其中pr,pc代表玩家的位置;br,bc代表箱子的位置。

用flag表示走过的位置不能再走。

一开始我想直接用dfs搜是不是就可以呢?后来发现,dfs走的路径不代表就是最优路径。无权图的最短路难道不是BFS。接着再用BFS试了一发,发现也不对。因为我们在这里需要优化的不是玩家走的最少的步数。而是推箱子次数最少的次数。

今天学习到了一种新型的BFS,双向队列BFS。这种BFS可以解决这种问题。这里,我们有一种思想就是优先走不推箱子的步子。为什么这样呢?因为优先走完这些状态后,我们再考虑走推箱子的步子,这样子才能最优。这也叫0 1 路径,即边权中有0又有1的最短路问题。以前的BFS解决的是边权都是1,现在有一些边权为0的边出现了怎么办?但是我们还是想以最短路径来走。这时候我们让权值为0的插队头,权值为1的插队尾即可!没有其它需要改变的!

class Solution {
public:
    static const int MAXN=25;
    int flag[MAXN][MAXN][MAXN][MAXN];
    const int INF=1e9;
    int minPushBox(vector<vector<char>>& grid) {
        int sr,sc;
        int br,bc;
        int desr,desc;
        int n=grid.size();
        int m=grid[0].size();
        for(int i=0;i<(int)grid.size();i++)
            for(int j=0;j<(int)grid[i].size();j++)
                if(grid[i][j]=='S')grid[i][j]='.',sr=i,sc=j;
                else if(grid[i][j]=='B')grid[i][j]='.',br=i,bc=j;
                else if(grid[i][j]=='T')grid[i][j]='.',desr=i,desc=j;     
        memset(flag,0,sizeof(flag));
        const int dr[]={0,-1,0,1};
        const int dc[]={-1,0,1,0};
        int ans=INF;
        int push=0;
        

        push=0;
        flag[sr][sc][br][bc]=1;
        ans=INF;
        deque<vector<int>> q;
        vector<int> tmp;
        tmp.push_back(sr);
        tmp.push_back(sc);
        tmp.push_back(br);tmp.push_back(bc);tmp.push_back(0);
        q.push_back(tmp);
        while(!q.empty()){
            vector<int> f=q.front();q.pop_front();
            int sr=f[0];int sc=f[1];int br=f[2];int bc=f[3];int push=f[4];
            if(br==desr && bc==desc){ans=push;break;}
             for(int i=0;i<4;i++){
                int nr=sr+dr[i];
                int nc=sc+dc[i];
                if(nr<0 || nr>=n || nc<0 || nc>=m)continue;
                if(grid[nr][nc]=='#')continue;
                if(flag[nr][nc][br][bc])continue;
                if(nr==br && nc==bc){
                    if(sc==nc-1){
                        if(nc<m-1  && grid[nr][nc+1]!='#'){
                            flag[nr][nc][nr][nc+1]=1;
                            vector<int> tmp;
                            tmp.push_back(nr);
                            tmp.push_back(nc);
                            tmp.push_back(nr);
                            tmp.push_back(nc+1);
                            tmp.push_back(push+1);
                            q.push_back(tmp);

                        }
                    }else if(sc==nc+1){
                        if(nc>0 && grid[nr][nc-1]!='#'){
                            flag[nr][nc][nr][nc-1]=1;
                            vector<int> tmp;
                            tmp.push_back(nr);
                            tmp.push_back(nc);
                            tmp.push_back(nr);
                            tmp.push_back(nc-1);
                            tmp.push_back(push+1);
                            q.push_back(tmp);
                        }
                    }else if(sr==nr-1){
                        if(nr<n-1 && grid[nr+1][nc]!='#'){
                            flag[nr][nc][nr+1][nc]=1;
                            vector<int> tmp;
                            tmp.push_back(nr);
                            tmp.push_back(nc);
                            tmp.push_back(nr+1);
                            tmp.push_back(nc);
                            tmp.push_back(push+1);
                            q.push_back(tmp);
                        }
                    }else if(sr==nr+1){
                        if(nr>0 && grid[nr-1][nc]!='#'){
                            flag[nr][nc][nr-1][nc]=1;
                            vector<int> tmp;
                            tmp.push_back(nr);
                            tmp.push_back(nc);
                            tmp.push_back(nr-1);
                            tmp.push_back(nc);
                            tmp.push_back(push+1);
                            q.push_back(tmp);
                        }
                    }
                }else{
                    flag[nr][nc][br][bc]=1;
                    vector<int> tmp;
                    tmp.push_back(nr);
                    tmp.push_back(nc);
                    tmp.push_back(br);
                    tmp.push_back(bc);
                    tmp.push_back(push);
                    q.push_front(tmp);
                }
            }

        }

        if(ans==INF)return -1;
        else return ans;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值