hdu_1254_推箱子(双BFS)

7 篇文章 0 订阅

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1254

题解:以箱子为主体,第一层BFS,然后用第二层BFS来判断人是否可以到达,这里细节比较多,要注意

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define FFC(i,a,b) for(int i=a;i<=b;i++)
struct dtm{int x,y,t;};
struct dtb{int x,y,t,mx,my;};
int g[10][10],gg[10][10],t,m,n,x1,y1,x2,y2,d[][2]={1,0,-1,0,0,1,0,-1};
bool v[10][10][4],f[10][10];
bool checkmen(int x,int y){
	if(f[x][y]||x<1||x>n||y<1||y>m||gg[x][y]!=0)return 0;
	return 1;
}
bool checkbox(int x,int y,int i){
	if(v[x][y][i]||x<1||x>n||y<1||y>m||g[x][y]==1)return 0;
	return 1;
}
int bfs(int sx,int sy,int ex,int ey){
	if(ex<1||ex>n||ey<1||ey>m)return -1;
	memset(f,0,sizeof(f));
	dtm s,o;s.x=sx,s.y=sy,s.t=0,f[sx][sy]=1;
	queue<dtm>Q;Q.push(s);
	while(!Q.empty()){
		o=Q.front();Q.pop();
		if(o.x==ex&&o.y==ey)return o.t;
		for(int i=0;i<4;i++){
			int xx=o.x+d[i][0],yy=o.y+d[i][1];
			if(!checkmen(xx,yy))continue;
			s.x=xx,s.y=yy,s.t=t+1,f[xx][yy]=1;
			Q.push(s);
		}
	}
	return -1;
}
int fuck(){
	memset(v,0,sizeof(v));
	dtb s,o;s.x=x1,s.y=y1,s.mx=x2,s.my=y2,s.t=0;
	queue<dtb>Q;Q.push(s);
	while(!Q.empty()){
		o=Q.front();Q.pop();
		if(g[o.x][o.y]==3)return o.t;
		for(int i=0;i<4;i++){
			int xx=o.x+d[i][0],yy=o.y+d[i][1],ok;
			if(!checkbox(xx,yy,i))continue;
			gg[o.x][o.y]=2;
			ok=bfs(o.mx,o.my,o.x-d[i][0],o.y-d[i][1]),gg[o.x][o.y]=0;
			if(ok==-1)continue;
			s.x=xx,s.y=yy,s.mx=o.x,s.my=o.y,s.t=o.t+1,v[xx][yy][i]=1;
			Q.push(s);
		}
	}
	return -1;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		FFC(i,1,n)FFC(j,1,m){
			scanf("%d",&g[i][j]);
			gg[i][j]=(g[i][j]==1?1:0);
			if(g[i][j]==2)x1=i,y1=j;
			if(g[i][j]==4)x2=i,y2=j;
		}
		printf("%d\n",fuck()); 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值