zoukankan      html  css  js  c++  java
  • hdoj--1254--推箱子(bfs好题)

    

    推箱子

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 6758    Accepted Submission(s): 1906


    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
     

    Author
    Ignatius.L & weigang Lee

    感觉还是有难度的,刚开始的时候没考虑人所在的位置,这里有一个坑,箱子移动的时候人必须在箱子后边,这样才可以推到箱子,这样的话就会有点复杂,每次推箱子的时候我们都应该判断一下,上一次人所在的位置是否可以到达这次推箱子的位置,所以这就不只是一个bfs可以搞定的了,在结构体中我们记录的应该有箱子和人的位置以及当前步数,每一次位置变换都应该更新人还有箱子的位置,同时判定该方案的可行性(加上了注释就CE了,不知道是什么鬼)
    #include<stdio.h>
    #include<cstring>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int map[10][10],mark[10][10][10][10];
    int n,m,flag,markk[10][10];
    int xiangx,xiangy;
    struct dian
    {
       int x,y;
       int renx,reny;
       int step;    
    }st,end;
    struct ren
    {
       int x,y;	
    }vv,stt;
    int bffs(ren stt)
    {
    	queue<ren>q;
    	markk[stt.x][stt.y]=1;
    	q.push(stt);
    	ren v,vn;
    	while(!q.empty())
    	{
    		vn=q.front();
    		q.pop();
    		if(vn.x==vv.x&&vn.y==vv.y)  
    		return 1;//可以到达现在推箱子的位置 	
    		for(int i=0;i<4;i++)
    		{
    			v.x=vn.x+dx[i];
    			v.y=vn.y+dy[i];
    			if(v.x>=n||v.x<0||v.y>=m||v.y<0) 
    			continue;//不能出界 
    			if(map[v.x][v.y]==1)	continue;
    			if(v.x==xiangx&&v.y==xiangy)  continue;
    			//不能在以前箱子所在的位置 
    			if(markk[v.x][v.y])  continue;
    			markk[v.x][v.y]=1;
    			q.push(v);
    		}
    	}	
    	return 0;
    }
    void bfs(dian st)
    {
    	queue<dian>p;
    	p.push(st);//使用人还有箱子的位置实现四维标记 
    	mark[st.x][st.y][st.renx][st.reny]=1;    
    	dian v,vn;
    	while(!p.empty())
    	{   
    		vn=p.front();
    		p.pop();
    		if(vn.x==end.x&&vn.y==end.y)
    		{//如果现在箱子被推到了指定的位置 
    			flag=1;
    			printf("%d
    ",vn.step);
    			return;
    		}    
    		for(int i=0;i<4;i++)
    		{//箱子位置变更 
    			v.x=vn.x+dx[i];
    			v.y=vn.y+dy[i];
    			v.step=vn.step+1;
    			v.renx=vn.x;
    			v.reny=vn.y;
    			vv.x=vn.x-dx[i];//vv中的x,y存储了推箱子时人应该在的位置 
    			vv.y=vn.y-dy[i];
    			if(v.x>=n||v.x<0||v.y>=m||v.y<0)  continue; 
    			if(map[v.x][v.y]==1)  continue;
    			if(map[vv.x][vv.y]==1||vv.x>=n||vv.x<0||vv.y>=m||vv.y<0)  continue;
    			if(mark[v.x][v.y][v.renx][v.reny])  continue;
    			stt.x=vn.renx;//结构体中存放的有当时人的位置 
    			stt.y=vn.reny;
    			xiangx=vn.x;
    			xiangy=vn.y;
    			memset(markk,0,sizeof(markk));
    			if(!bffs(stt))  continue;//箱子被推之前的位置,因为还要判定是否可以推 
    			mark[v.x][v.y][v.renx][v.reny]=1;
    			p.push(v);
    		}
    	}
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		flag=0;
    		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)
    			{
    				st.x=i;
    				st.y=j;
    				xiangx=i;
    				xiangy=j;
    			}
    			if(map[i][j]==3)
    			{
    				end.x=i;
    				end.y=j;
    			}
    			if(map[i][j]==4)
    			{
    				st.renx=i;
    				st.reny=j;	
    			}
    		}
    		st.step=0;
    		memset(mark,0,sizeof(mark));
    		memset(markk,0,sizeof(markk));
    		bfs(st);    
    		if(!flag)  printf("-1
    ");    
    	}    
    	return 0;
    }

  • 相关阅读:
    对抽象编程:接口和抽象类
    工厂方法模式
    用例建模Use Case Modeling
    分析一套源代码的代码规范和风格并讨论如何改进优化代码
    结合工程实践选题调研分析同类软件产品
    如何提高程序员的键盘使用效率
    Java复习面试指南01什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
    Mac系统下MySql下载MySQL5.7及详细安装流程
    Java复习面试指南02JDK和JRE的区别?程序从源代码到运行经历哪几步?
    毕业半年小结
  • 原文地址:https://www.cnblogs.com/playboy307/p/5273378.html
Copyright © 2011-2022 走看看