hdu 推箱子

这是一个搜索题,双重搜索题,思路如下:

在箱子移动到任何一个位置之前,首先要判断小人能不能走到推箱子的位置,如果能,再继续推,如果不能,则不推。

另外这个题需要注意的细节比较多

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值