hdu 1254 推箱子

用BFS让箱子走一遍即可。

其中判断箱子能否往前走,除了看它前面是否为墙,还要判断人能不能到它后面的方格。

还有标记状态,箱子和人有一个位置不同,便是不同的状态。我用的哈希判重,其实开个四维数组也行,毕竟数据范围不大。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>

#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define FOR(i,s,t) for(int i = (s) ; i <= (t) ; ++i )

#define lchild o<<1
#define rchild o<<1|1

typedef long long ll;
typedef unsigned long long ull;

using namespace std;

const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=10007;

int dir[4][2]={0,-1,0,1,-1,0,1,0};

int t,m,n,ans;
int mp[10][10];

struct node
{
	int bx,by,px,py;//箱子的坐标和人的坐标
	int step;

	inline int operator==(const node & a)
    {
        if( bx!=a.bx )return false;
        if( by!=a.by )return false;
        if( px!=a.px )return false;
        if( py!=a.py )return false;
        return true;
    }
    bool friend operator<(node a,node b)
    {
        return a.step>b.step;
    }
};

node start;
vector <node> v[maxn];

int myhash(node a){
	return (a.bx * 11 + a.by*111 + a.px*1111 + a.py*11111 ) % maxn;
}

bool ok(int x,int y){
    if( x<0 || x>=m )return false;
    if( y<0 || y>=n )return false;
    if( mp[x][y]==1 )return false;
    return true;
}

bool visit(node a){
	int ha = myhash(a);
	int num = v[ha].size();
	for(int i=0 ; i<num ; ++i){
		if( v[ha][i] == a ){
			//printf("has vised this state.\n");
			return true;
		}
	}
	v[ha].push_back(a);
	return false;
}

bool cango(node a,int sx,int sy){
	//printf("box : %d,%d ; if can go to %d,%d \n",a.bx,a.by,sx,sy );

	//bfs判断人能否到达mp[sx][sy]
	node now=a,next;

	bool vis[10][10];
	memset(vis,0,sizeof vis);
	vis[now.px][now.py]=1;
	queue<node>q2;
	q2.push(now);

	while(!q2.empty()){
		now=q2.front();
		q2.pop();
		//printf("now peo:: %d,%d\n",now.px,now.py );
		if(now.px==sx && now.py==sy){
			return true;
		}
		for(int i=0;i<4;++i){
			int nx = now.px+dir[i][0];
			int ny = now.py+dir[i][1];

			if( !ok(nx,ny) )continue;
			if( vis[nx][ny])continue;
			if( nx == now.bx && ny == now.by )continue;

			vis[nx][ny]=1;

			next.bx=now.bx;
			next.by=now.by;
			next.px=nx;
			next.py=ny;
			next.step=now.step+1;
			//printf("    next peo:: %d,%d\n",next.px,next.py );
			q2.push(next);
		}
	}
	return false;
}

int bfs(){
	node now = start,next ;
    priority_queue <node> q;
	q.push(now);
    visit(now);
	while( !q.empty() ){
		now=q.top();
		q.pop();
		//printf("now box:: %d,%d\n",now.bx,now.by );
		if( mp[now.bx][now.by]==3 ){
			return now.step;
		}
		for(int i=0;i<4;++i){

			int nx = now.bx + dir[i][0];
			int ny = now.by + dir[i][1];
			if( !ok(nx,ny) )continue;

			int lx = now.bx - dir[i][0];
			int ly = now.by - dir[i][1];
			if( !ok(lx,ly) )continue;

			if( cango(now,lx,ly) ){
				next.bx=nx;
				next.by=ny;
				next.px=now.bx;
				next.py=now.by;
				next.step=now.step+1;

				if( !visit(next) ) q.push(next);
			}
		}
	}
	return -1;
}

int main()
{
	//freopen("in.txt","r",stdin);
	Ri(t);
	while(t--){
		for(int i=0;i<maxn;++i)v[i].clear();
		Ri(m);Ri(n);
		for(int i=0;i<m;++i){
			for(int j=0;j<n;++j){
				Ri( mp[i][j] );

				if(mp[i][j]==2){
					start.bx=i;
					start.by=j;
				}else if(mp[i][j]==4){
					start.px=i;
					start.py=j;
					start.step=0;
				}
				//printf("%d ",mp[i][j] );
			}
			//printf("\n");
		}
		ans=bfs();
		printf("%d\n",ans );
	}
	return 0;
}

 

posted @ 2015-12-10 15:15  纸牌  阅读(123)  评论(0编辑  收藏  举报