hdu 1254 推箱子
终于还是AC了,可是WA了N多次了呀,唉,忽略了一个要点,就是在广搜的时候,一个点可以不止被通过一次,好郁闷呀,确实如此,看了大牛给的测试例子,通过了这个例子,接着就AC了
得再开一个数组记录到达该点的方向
主体是用BFS枚举所有可推点的状态,用DFS判断推箱工能否到达箱子的后面
看下这个测试例子
5 3
0 0 0
0 0 0
0 2 0
1 4 1
1 3 1
答案是 4
#include<iostream>
#include<queue>
using namespace std;
int map[8][8],n,m,ei,ej,a,b,dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
//(ei,ej)表示每次DFS的终点,(a,b)表示推箱工的起始位置
bool vis[8][8][4];
bool vis1[8][8];
struct node
{
int x,y,cnt,di;
friend bool operator <(const node &c,const node &d)
{
return c.cnt>d.cnt;
}
};
node f;
int dfs(int i,int j)
{
if(i==ei&&j==ej)
return 1;
for(int k=0;k<4;k++)
{
int c=i+dir[k][0];
int d=j+dir[k][1];
if(c>n||c<1||d>m||d<1||map[c][d]==1||vis1[c][d])
continue;
vis1[c][d]=1;
if(dfs(c,d)) return 1;
}
return 0;
}
void bfs()
{
priority_queue<node> Q;
Q.push(f);
while(!Q.empty())
{
node t=Q.top(),temp;
Q.pop();
for(int k=0;k<4;k++)
{
int i=t.x+dir[k][0];
int j=t.y+dir[k][1];
ei=t.x-dir[k][0];//表示要向此方向推时箱子的后方
ej=t.y-dir[k][1];
if(i>n||i<1||j>m||j<1||vis[i][j][k]||map[i][j]==1)continue;
if(ei>n||ei<1||ej>m||ej<1||map[ei][ej]==1)continue;
memset(vis1,0,sizeof(vis1));
if(t.di!=-1)
{
//(t.x,t.y)表示此刻箱子的位置,(t.x-dir[t.di][0],t.x-dir[t.di][1])表示人的位置
vis1[t.x][t.y]=1;vis1[t.x-dir[t.di][0]][t.y-dir[t.di][1]]=1;
if(!dfs(t.x-dir[t.di][0],t.y-dir[t.di][1])) continue;
}
else {
vis1[a][b]=1;vis1[t.x][t.y]=1;
if(!dfs(a,b)) continue;
}
if(map[i][j]==3)
{
cout<<t.cnt+1<<endl;
return ;
}
if(map[i][j]==0||map[i][j]==4||map[i][j]==2)
{
temp.cnt=t.cnt+1;temp.di=k;
temp.x=i;temp.y=j;
Q.push(temp);
vis[i][j][k]=1;
}
}
}
cout<<-1<<endl;
}
int main()
{
int cas;
cin>>cas;
while(cas--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]==2)
f.x=i,f.y=j;
if(map[i][j]==4)
a=i,b=j;
}
f.cnt=0;f.di=-1;
memset(vis,0,sizeof(vis));
bfs();
}
return 0;
}