两种搜索结合的一道题目。题目要求箱子到终点要动几次,显然要用BFS;然而箱子的四个可能的移动方向并不一定是可行的,因为根据推箱子的游戏规则,必须要有人在箱子一侧推,才可使得箱子移动,因此需用DFS或BFS判断人能否到达箱子的一侧。个人认为在判断人能否到达的时候,用DFS更好一些,因为并不需要求人到箱子的一侧需要的最少步数。
本题要用两个vis数组。一个vis数组对应箱子的移动,只需在每次执行一次样例前memset即可,因为只要在一次样例中,只要已经有方案到达过某格,之后到达该格的其他方案所需时间必定大于等于第一个方案到达该格的时间;另一个vis数组需要在每次搜索判断人能否到达前,都memset一次,因为数组不大,我当时就直接在子函数里声明了。
注意人不能出边界,也不能踩在箱子上23333。箱子当然也不能出边界。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;
int t,m,n;
int map[8][8];
int dir[4][2]={0,1,0,-1,-1,0,1,0};
struct Node
{
int manx,many,thx,thy;
int num;
};
int visited[8][8][4];
int bfs(struct Node o,int x,int y)
{
int vis[8][8];
memset(vis, 0, sizeof(vis));
queue<Node> st;
st.push(o);
while(!st.empty())
{
struct Node no1,no2;
no1=st.front();
st.pop();
if(no1.manx==x&&no1.many==y)
{
return 1;
}
for(int i=0;i<4;i++)
{
no2=no1;
no2.manx+=dir[i][0];
no2.many+=dir[i][1];
if(no2.manx==no2.thx&&no2.many==no2.thy)
continue;
if(no2.manx<0||no2.manx>=m||no2.many<0||no2.many>=n)
continue;
if(vis[no2.manx][no2.many])
{
//printf(" -1");
continue;
}
if(map[no2.manx][no2.many]==1)
continue;
vis[no2.manx][no2.many]=1;
st.push(no2);
}
}
return -1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
int ans=-1;
scanf("%d%d",&m,&n);
struct Node first;
queue<Node> q;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==2)
{
first.thx=i;
first.thy=j;
}else if (map[i][j]==4)
{
first.manx=i;
first.many=j;
}
}
first.num=0;
memset(visited, 0, sizeof(visited));
q.push(first);
while(!q.empty())
{
struct Node order,next;
order=q.front();
q.pop();
if(map[order.thx][order.thy]==3)
{
ans=order.num;
break;
}
for(int i=0;i<4;i++)
{
next=order;
next.manx=next.thx;
next.many=next.thy;
next.thx+=dir[i][0];
next.thy+=dir[i][1];
if(next.thx<0||next.thx>=m||next.thy<0||next.thy>=n)
continue;
if(visited[next.thx][next.thy][i])
continue;
if(map[next.thx][next.thy]==1)
continue;
int x,y;
x=next.manx-dir[i][0];
y=next.many-dir[i][1];
if(x<0||x>=m||y<0||y>=n)
continue;
int b=bfs(order,x,y);
if(b== -1)
continue;
visited[next.thx][next.thy][i]=1;
next.num++;
q.push(next);
}
}
printf("%d\n",ans);
}
return 0;
}