您的位置:首页 > 其它

hdu1254推箱子

2015-04-27 18:55 253 查看
题意:不用说了吧,都玩过的,只是坑多

思路:bfs+bfs

第一遍广搜,搜索箱子能走的位置有哪些,坑点出来的,箱子走过的也是能走的哦!只是从同一个方向来的不能走。

箱子入队的条件:

1.箱子能到达某个位置

2。人能到达推箱子的位置,并且能推动箱子。(于是第二个广搜嵌套进来了)

相对于箱子,人的广搜就好跑多了,只要人没走过,并且在范围内,并且不是墙,不是箱子,就能走。普通的广搜

同时还有许多细节问题,看代码有解释

#include<stdio.h>

#include<queue>

#include<string.h>

using namespace std;

struct thing

{
int x,y,step;
int px,py;    //每一次推箱子,人都会站在推箱子的位置上而不是箱子的位置,但是箱子可以向多个方向推,所以就要用结构体记录每次人站的位置 

};

struct people

{
int xx,yy;

};

int map[25][25];

int dir[4][2]={1,0,0,1,-1,0,0,-1};//方向,两个广搜都能用 

int n,m;//标记地图大小的 

int x1,x2,y1,y2;//物块初始位置和结束位置

int px1,px2,py1,py2;//人每次要从一个位置到另外一个位置去推箱子

int thing_mark[25][25],people_mark[25][25];

bool thing_go(int x,int y)

{
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=1) return 1;//只要不是墙,就可以走,因为箱子是可以走走过的路,除了从同一个方向来的 
return 0;

}

bool people_go(int xxx,int yyy)

{
if(xxx>=0&&yyy>=0&&xxx<n&&yyy<m&&map[xxx][yyy]!=1&&people_mark[xxx][yyy]==0) return 1;
return 0;//人就不能走经过的路了,所以人是正常的搜索 

}

int people_bfs()

{
int j;
queue<people>p;
people cur,tail;
cur.xx=px1;
cur.yy=py1;
people_mark[px1][py1]=1;
memset(people_mark,0,sizeof(people_mark));//清零,因为thing_bfs()运行一遍,会调用几次这个函数,所以每次使用都要清空 
p.push(cur);
while(!p.empty())
{
cur=p.front();
p.pop();
if(cur.xx==px2&&cur.yy==py2) 
{
return 1;
}
// printf("people::%d %d\n",cur.xx,cur.yy);
for(j=0;j<4;j++)
{
tail.xx=cur.xx+dir[j][0];
tail.yy=cur.yy+dir[j][1];
if(people_go(tail.xx,tail.yy))
{
people_mark[tail.xx][tail.yy]=1;
p.push(tail);
}
}
}
return 0;

}

int thing_bfs()

{
int i,can;
queue<thing>q;
thing first,last;
first.x=x1;
first.y=y1;
first.step=0;
first.px=px1;
first.py=py1;
q.push(first);
while(!q.empty())
{
first=q.front();
q.pop();
// printf("thing::%d %d\n",first.x,first.y);
for(i=0;i<4;i++)
{
can=0;
if(map[first.x+1][first.y]==1||first.x==0||first.x==n-1||map[first.x-1][first.y]==1)
{
if(i==0||i==2) continue;
}
if(map[first.x][first.y+1]==1||first.y==0||first.y==m-1||map[first.x][first.y-1]==1)
{
if(i==1||i==3) continue;
}//一侧是墙或者是边界,则两边不能推动,同理死胡同就能解决 
last.x=first.x+dir[i][0];
last.y=first.y+dir[i][1];
last.step=first.step+1;
px1=first.px;py1=first.py;
if(i==thing_mark[last.x][last.y]) continue;
if(thing_go(last.x,last.y))
{           
px2=first.x-dir[i][0];
py2=first.y-dir[i][1];
map[first.x][first.y]=1;//有箱子的位置,人不能穿过,所以把箱子看成墙 
can=people_bfs();
map[first.x][first.y]=0;//判断完之后还要把箱子还原,否则该位置会一直变成墙 
if(can)
{
if(last.x==x2&&last.y==y2) return last.step;//同一个位置并且同一个方向则不入队 
thing_mark[last.x][last.y]=i;//标记箱子是从哪个方向来的,
last.px=px2;last.py=py2;
q.push(last);
}
}
}
}
return -1;

}

int main()

{
int i,j,cases,time;
scanf("%d",&cases);
while(cases--)
{
memset(map,0,sizeof(map));
memset(thing_mark,-1,sizeof(thing_mark));
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==2)
{
x1=i;y1=j;
}
else if(map[i][j]==3)
{
x2=i;y2=j;
}
else if(map[i][j]==4)
{
px1=i;py1=j;
}
}
}
time=thing_bfs();
printf("%d\n",time);
}
return 0;

}

测试数据

100

5 5

0 3 0 0 0

1 0 1 4 0

0 0 1 0 0

1 0 2 0 0

0 0 0 0 0

4 4

0 0 3 0

0 1 0 1

0 1 0 1

0 0 2 4

5 4

0 0 3 0

0 1 0 1

0 1 0 1

0 0 2 4

0 0 0 0

3 4

1 1 0 0 

0 2 4 3

1 1 0 0

3 4 

1 1 0 0 

3 2 4 0 

0 0 0 0

5 5

0 4 0 0 0

1 2 1 0 0

3 0 0 1 0

1 0 0 1 0

1 0 0 1 0

4 3

0 0 0

0 0 1

0 2 3

1 4 1

6 3

0 0 0

0 0 0

1 0 0

0 0 1

0 2 3

1 4 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu 博客 acm 搜索 bfs+bfs