题意:
在推箱子游戏中,怎么求人物为了把箱子推到终点所需要的推箱子次数最少的次数。
解题思路:
这题的题目数据非常小,考虑用暴力搜索的方法。很自然地我们可以建立状态
其中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;
}
};