hdu1254推箱子

题意:不用说了吧,都玩过的,只是坑多

思路: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


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值