hdu 1254 推箱子



Problem Description
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.


 

Input
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
 

Output
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
 

Sample Input
1 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
 

Sample Output
4
写了好久,思路很明显,但是奈何搜索写的太少,很多细节让我一直错。
1.解决搜索时人走的路的标记
2.解决搜索时箱子走的路的标记
3.解决搜索中箱子和人位置的变换
我写的人用深搜,箱子用广搜。却W,过不了,具体那错,我还没找到;
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m;
bool flag,vv[10][10];
int map[10][10];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct node{
    int x,y,step;
    int mmap[10][10];
    bool check(){
        if(x>=0&&x<n&&y>=0&&y<m)
            return true;
        return false;
    }
}s,e,t,w,mm,man,mans;
int dfs(int a,int b){
   if(flag) return 1;
   if(map[a][b]==4){
      flag=true;return 1;
   }//printf("%d,%d---",a,b);
   for(int j=0;j<4;j++){
      mm.x=a+dir[j][0];
      mm.y=b+dir[j][1];
      if(mm.check()&&!vv[mm.x][mm.y]&&map[mm.x][mm.y]!=1&&map[mm.x][mm.y]!=2){
         vv[mm.x][mm.y]=true;
         dfs(mm.x,mm.y);
         vv[mm.x][mm.y]=false;
      }
   }

}
int bfs(){
   bool v[10][10][4];
   memset(v,false,sizeof(v));
   queue<node>qu;
   qu.push(s);
   while(!qu.empty()){
       t=qu.front();
       qu.pop();
       for(int i=0;i<4;i++){
           w=t;
           w.x=t.x+dir[i][0];
           w.y=t.y+dir[i][1];
           w.step++;
           if(w.check()&&!v[w.x][w.y][i]&&map[w.x][w.y]!=1){
              man.x=t.x-dir[i][0];
              man.y=t.y-dir[i][1];
              if(man.check()){
                flag=false;
                memset(vv,false,sizeof(vv));
                dfs(man.x,man.y);
                if(flag){
                    swap(w.mmap[w.x][w.y],w.mmap[t.x][t.y]);
                    swap(w.mmap[man.x][man.y],w.mmap[mans.x][mans.y]);
                    v[w.x][w.y][i]=true;
                    //printf("%d,%d-->>%d,%d_%d\n",t.x,t.y,w.x,w.y,w.mmap[w.x][w.y]);
                    if(map[w.x][w.y]==3)
                        return w.step;
                    qu.push(w);
                }
              }
           }
       }
   }
   return -1;
}
int main(){
   int T;
   scanf("%d",&T);
   while(T--){
      scanf("%d%d",&n,&m);
      for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            scanf("%d",&map[i][j]);
            if(map[i][j]==2){
                s.x=i;
                s.y=j;
                s.step=0;
            }
            if(map[i][j]==4){
                mans.x=i;
                mans.y=j;
            }
        }
        printf("%d\n",bfs());
   }
}
下面是正确代码,用两个广搜。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

int n,m,T;
int dir[4][2]={0,1,0,-1,1,0,-1,0};
int str[10][10];
struct node{
	int x,y,step;
	int mmap[10][10];
	bool check(){
		if(x>=0&&x<n&&y>=0&&y<m)
			return true;
		return false;
	}
}s,e,u,v,ss,ee,uu,vv;
bool bfs(node p){           //搜索人是否能到达指定位置
	queue<node>que;
	ss=p;
	bool flag[10][10];
	memset(flag,false,sizeof(flag));
	for(int i=0;i<n;i++){   //找到人的起点
		for(int j=0;j<m;j++)
			if(p.mmap[i][j]==4){
				ss.x=i;
				ss.y=j;
				ss.step=0;
			}
	}
	if(ss.x==ee.x&&ss.y==ee.y)
		return true;
	que.push(ss);
	flag[ss.x][ss.y]=true;
	while(!que.empty()){
		uu=que.front();
		que.pop();
		for(int i=0;i<4;i++){
			vv=uu;         
			vv.step++;     //记步
			vv.x+=dir[i][0];
			vv.y+=dir[i][1];
			if(vv.check()&&flag[vv.x][vv.y]==false&&(p.mmap[vv.x][vv.y]!=1&&p.mmap[vv.x][vv.y]!=2)){ //目标点不是墙也不是箱子
				flag[vv.x][vv.y]=true;
				if(vv.x==ee.x&&vv.y==ee.y)
					return true;
				que.push(vv);
			}
		}
	}
	return false;
}
int bfs(){ //搜索箱子路径
	int flag[10][10][4];
	queue<node>que;
	que.push(s);
	memset(flag,false,sizeof(flag));
	while(!que.empty()){
		u=que.front();
		que.pop();
		for(int i=0;i<4;i++){
			v=u;
			v.x+=dir[i][0];
			v.y+=dir[i][1];
			v.step++;
			if(v.check()&&str[v.x][v.y]!=1&&flag[v.x][v.y][i]==false){//目标点不是墙
				ee.x=u.x-dir[i][0];                     //人的目标位置
				ee.y=u.y-dir[i][1];
				if(ee.check()){                         //不越界
                    if(bfs(v)){                         //可以走
                        swap(v.mmap[v.x][v.y],v.mmap[u.x][u.y]);//更新地图,箱子和人的位置
                        swap(v.mmap[ee.x][ee.y],v.mmap[ss.x][ss.y]);
                        flag[v.x][v.y][i]=true;
                        if(str[v.x][v.y]==3)
                            return v.step;
                        que.push(v);
                    }
				}
			}
		}
	}
	return -1;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++){
				scanf("%d",&str[i][j]);
				s.mmap[i][j]=str[i][j]; //把地图传到结构体中
				if(str[i][j]==2){       //标注箱子起点
					s.x=i;
					s.y=j;
					s.step=0;
				}
			}
			printf("%d\n",bfs());
	}
	return 0;
}



Problem Description
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.


 

Input
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
 

Output
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
 

Sample Input
1 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
 

Sample Output
4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值