这是一个搜索题,双重搜索题,思路如下:
在箱子移动到任何一个位置之前,首先要判断小人能不能走到推箱子的位置,如果能,再继续推,如果不能,则不推。
另外这个题需要注意的细节比较多
1 某个点可能多次走过,但是走的方向不同,如下面这个数据:
0 3 0
1 4 1
1 2 1
0 0 0
0 0 0
0 0 0
这里 很多点会多次走过,拿(4,2)举例,它会多次走过,但是它走过时人的位置不一样,一次是在(3,2),一次是在(5,2),这时就需要把这两种情况分别标记了防止出现在某个位置死循环推,解决方案是visit[][][][]这样的四维数组用来判断小人和箱子的位置,前两个用来标记箱子,后两个用来标记小人。
2 如何记录走了多少步
这了visit四维数组是无法记录的,原因是因为某个点多次走过时它无法判断这个点的来源状态是什么样的,比如在(4,2)到底是从(3,2)来的还是(5,2)来的,解决方案是再开一个二维数组,专门记录当前位移数,这样重复走某些位置也能把步数记录下来了。
3 需要实时更新箱子位置和小人位置
在交的时候错了两次,第一次是没有屏蔽额外的cout语句,第二次是因为在判断小人的位置时出了一个小bug,不过这个bug不是共病,也不是常犯bug,这里就不多说了。
代码如下:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int visit[10][10][10][10],visitp[10][10],ANS[10][10];
int map[10][10],px,py,endx,endy,ans=-1,m,n;
bool flag=false;
struct node{
int x,y;
};
node dian,DIAN;
void bfspeople(int fromx,int fromy,int endx,int endy){
queue<node>qq;
while(!qq.empty())qq.pop();
node d,D;
d.x=fromx;d.y=fromy;
qq.push(d);
int move[4][2]={0,1,1,0,0,-1,-1,0};
while(!qq.empty()){
d=qq.front();
qq.pop();
if(d.x==endx && d.y==endy){
//cout<<"!";
flag=true;
return ;
}
for(int i=0;i<4;i++){
D.x=d.x+move[i][0];
D.y=d.y+move[i][1];
if(visitp[D.x][D.y]==0 && map[D.x][D.y]!=1 && map[D.x][D.y]!=2 && D.x>=1 && D.x<=m && D.y>=1 && D.y<=n){
visitp[D.x][D.y]=1;
qq.push(D);
}
}
}
}
void bfsbox(int x,int y){
queue<node>q;
queue<node>people;
while(!q.empty())q.pop();
while(!people.empty())people.pop();
node peopled,peopleD;
peopled.x=px;peopled.y=py;
people.push(peopled);
dian.x=x;dian.y=y;
q.push(dian);
int move[4][2]={0,1,1,0,0,-1,-1,0},lastx=0,lasty=0;
while(!q.empty()){
dian=q.front();
peopled=people.front();
people.pop();
q.pop();
for(int i=0;i<4;i++){
DIAN.x=dian.x+move[i][0];
DIAN.y=dian.y+move[i][1];
flag=false;
memset(visitp,0,sizeof(visitp));
map[dian.x][dian.y]=2;
// cout<<DIAN.x<<" "<<DIAN.y<<" "<<dian.x-move[i][0]<<" "<<dian.y-move[i][1]<<endl;
bfspeople(peopled.x,peopled.y,dian.x-move[i][0],dian.y-move[i][1]);
map[dian.x][dian.y]=0;
if(flag && map[DIAN.x][DIAN.y]!=1 && !visit[DIAN.x][DIAN.y][dian.x][dian.y] && DIAN.x>=1 && DIAN.y>=1 && DIAN.x<=m && DIAN.y<=n){
visit[DIAN.x][DIAN.y][dian.x][dian.y]=1;
ANS[DIAN.x][DIAN.y]=ANS[dian.x][dian.y]+1;
// cout<<DIAN.x<<" "<<DIAN.y<<" "<<ANS[DIAN.x][DIAN.y]<<endl;
q.push(DIAN);
peopleD.x=dian.x;peopleD.y=dian.y;
people.push(peopleD);
if(map[DIAN.x][DIAN.y]==3){
ans=ANS[DIAN.x][DIAN.y];
return ;
}
}
}
//cout<<endl;
}
}
int main(){
int x;
cin>>x;
while(x--){
memset(visit,0,sizeof(visit));
memset(map,0,sizeof(map));
memset(ANS,0,sizeof(ANS));
cin>>m>>n;
int bx,by;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>map[i][j];
if(map[i][j]==2){
bx=i;by=j;
}
if(map[i][j]==4){
px=i;py=j;
}
if(map[i][j]==3){
endx=i;endy=j;
}
}
}
ans=-1;
bfsbox(bx,by);
cout<<ans<<endl;
}
}
最后再附ji个个人想的测试数据:
5 4
0 3 1 0
0 4 1 0
0 2 0 0
1 0 1 0
0 0 0 0