传送门
题意
给出一副图
0.空地1.墙2.箱子3.目的地4.人所在的位置
问最少几步能将箱子推到目的地
分析
这道题难度略大(菜鸡),首先用vis[bx][by][mx][my]记录当箱子(bx,by)和人(mx,my)是否被访问过,用一个bfs求出最短路,另外dfs判断人是否能够到达推箱子的位置,写起来比较复杂,(弱鸡)
trick
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int t,n,m,mp[10][10],bx,by,mx,my,prex,prey,flag,ans;
int dir[4][2]={0,1,-1,0,0,-1,1,0};
int vis_p[10][10],vis[10][10][10][10];
struct node
{
int bx,by;
int mx,my;
int step;
}tmp,p;
bool check(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m&&mp[x][y]!=1) return 1;
return 0;
}
void dfs(int prex,int prey,int mx,int my)
{
if(prex==mx&&prey==my) { flag=1;return ; }
if(flag) return ;
for(int i=0;i<4;++i)
{
int x=prex+dir[i][0];
int y=prey+dir[i][1];
if(check(x,y)&&!vis_p[x][y])
{
vis_p[x][y]=1;
dfs(x,y,mx,my);
}
}
}
void bfs2(int bx,int by,int mx,int my)
{
memset(vis,0,sizeof(vis));
ans=-1;
queue<node>pq;
while(!pq.empty()) pq.pop();
tmp={bx,by,mx,my,0};
pq.push(tmp);
while(!pq.empty())
{
tmp=pq.front();pq.pop();
if(mp[tmp.bx][tmp.by]==3) { ans=tmp.step;return ; }
for(int i=0;i<4;++i)
{
p=tmp;
p.bx+=dir[i][0],p.by+=dir[i][1];
prex=tmp.bx-dir[i][0],prey=tmp.by-dir[i][1];
if(!check(p.bx,p.by)) continue;
if(!check(prex,prey)) continue;
if(vis[p.bx][p.by][prex][prey]) continue;
memset(vis_p,0,sizeof(vis_p));
vis_p[tmp.bx][tmp.by]= vis_p[prex][prey]=1;
flag=0;
dfs(prex,prey,tmp. mx,tmp.my);
if(!flag) continue;
vis[p.bx][p.by][prex][prey]=1;
p.mx=prex,p.my=prey;
p.step++;
pq.push(p);
}
}
}
int main()
{
for(scanf("%d",&t);t--;)
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
{
scanf("%d",&mp[i][j]);
if(mp[i][j]==4) { mx=i,my=j; }
if(mp[i][j]==2) { bx=i,by=j; }
}
bfs2(bx,by,mx,my);
printf("%d
",ans);
}
}
/*
6666
5 5
3 0 1 0 0
1 0 1 4 0
0 0 1 0 0
1 0 2 0 0
0 0 0 0 0
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
5 5
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 2 1 1
4 0 3 0 0
*/