【BFS+DFS】hdu 1254 推箱子

51 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=1254

分析:以箱子的路线为主,判断人是否能到达推箱子的地点,通过箱子只能走不同方向(vis[NM][NM][[4])一次标记

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;

const int NM=10;
int a[4][2]={-1,0,1,0,0,1,0,-1};
int vis[NM][NM][4],vp[NM][NM];
int n,m,x1,x2,y1,y2,A1,B1,flag;
int str[NM][NM];

struct Box{
	int bx,by,ans;
	int px,py;
};

bool check(int x,int y)
{
	if(x>=0&&x<n&&y>=0&&y<m&&str[x][y]!=1)
		return 1;	
	else return 0;
}

void DFS1(int xx1,int yy1,int xx2,int yy2)  //只是判断人能否到达,无论步数
{
	if(xx1==xx2&&yy1==yy2)
	{
		flag=1;
		return;
	}
	if(flag) return;
	for(int i=0;i<4;i++)
	{
		int x=xx1+a[i][0];
		int y=yy1+a[i][1];
		if(check(x,y)&&!vp[x][y])
		{
			vp[x][y]=1;
			DFS1(x,y,xx2,yy2);
		}
	}	
}

void BFS()
{
	queue<Box>q1;
	Box t,p;
	int i,xx1,xx2,yy1,yy2;
	
	memset(vis,0,sizeof(vis));
	t.bx=x1,t.by=y1;
	t.px=A1,t.py=B1;
	t.ans=0;
	q1.push(t);
	while(!q1.empty())
	{
		t=q1.front();q1.pop();
		if(t.bx==x2&&t.by==y2)
		{
			printf("%d\n",t.ans);
			return;
		}
		for(i=0;i<4;i++)
		{
			p.bx=t.bx+a[i][0],p.by=t.by+a[i][1];
			xx1=t.px,yy1=t.py;  //人起始位置
			xx2=t.bx-a[i][0],yy2=t.by-a[i][1];  //人要到达位置
			if(check(p.bx,p.by)&&check(xx2,yy2)&&!vis[t.bx][t.by][i])
			{
				memset(vp,0,sizeof(vp));
				vp[t.bx][t.by]=1;  //人不能穿过箱子
				flag=0;
				DFS1(xx1,yy1,xx2,yy2);
				if(!flag) continue;
				
				vis[t.bx][t.by][i]=1;
				p.px=xx2,p.py=yy2;
				p.ans=t.ans+1;
				q1.push(p);
			}
		}
	}
	printf("-1\n");
}

int main()
{
	int i,j,T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
			for(i=0;i<n;i++)
			{
				for(j=0;j<m;j++)
				{
					scanf("%d",&str[i][j]);
					if(str[i][j]==2)
						x1=i,y1=j;
					else if(str[i][j]==3)
						x2=i,y2=j;
					else if(str[i][j]==4) //人
						A1=i,B1=j;
				}
			}	
			BFS();
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值