这题跟 hdu 1734 push box 是一样的,只不过这题推的是一个箱子,另外求的是箱子被推了多少次,那么只要在箱子被推的时候 次数才加1,然后使用优先队列就ok了
写了1734就会觉得这题很水啦 HDU1734题解
网上主流的都是bfs+bfs,或者是bfs+dfs
<span style="font-size:18px;">#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
int map[9][9],n,m;
bool hash[9][9][9][9];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct node
{
int x,y;
};
struct state
{
node h,box;
int st;
bool operator<(const state& p)const
{
return st>p.st;
}
bool isok()
{
if(h.x>=0&&h.x<n&&h.y>=0&&h.y<m&&map[h.x][h.y]!=1) return true;
return false;
}
}a,b;
void sethash(state cur)
{
hash[cur.h.x][cur.h.y][cur.box.x][cur.box.y]=true;
}
bool gethash(state cur)
{
return hash[cur.h.x][cur.h.y][cur.box.x][cur.box.y];
}
bool find(state cur)
{
if(map[cur.box.x][cur.box.y]==3) return true;
return false;
}
bool isbox(state cur)
{
if(cur.h.x==cur.box.x&&cur.h.y==cur.box.y) return true;
return false;
}
bool logic(state cur,int d)
{
state next;
next.h.x=cur.h.x+dir[d][0];
next.h.y=cur.h.y+dir[d][1];
if(!next.isok()) return false;
return true;
}
int bfs()
{
priority_queue<state> q;
a.st=0;
q.push(a);
while(!q.empty()){
a=q.top(),q.pop();
if(find(a)){
return a.st;
}
for(int i=0;i<4;++i){
b=a;
b.h.x=a.h.x+dir[i][0];
b.h.y=a.h.y+dir[i][1];
if(!b.isok()) continue;
if(isbox(b)){
if(logic(b,i)){
b.box.x+=dir[i][0];
b.box.y+=dir[i][1];
b.st++;
if(!gethash(b)){
sethash(b);
q.push(b);
}
}
}
else{
if(!gethash(b)){
sethash(b);
q.push(b);
}
}
}
}
return -1;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int t;
cin>>t;
while(t--){
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){
a.box.x=i;
a.box.y=j;
}
if(map[i][j]==4){
a.h.x=i;
a.h.y=j;
}
}
}
memset(hash,false,sizeof hash);
sethash(a);
printf("%d\n",bfs());
}
return 0;
}</span>
BFS+DFS
dfs出人能到达的点,用一个2维数组标记,然后要想能够推箱子,那么人必须站在箱子的后面,那么我们只要判断人能不能到达箱子的后方,箱子的前方是不是空地就OK啦
在bfs中嵌套dfs
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define M 9
using namespace std;
int map[M][M];
bool vis[M][M][4];
bool pvst[M][M];
int dir[4][2]={{0,1},{-1,0},{0,-1},{1,0}};//方向为 右上左下
int n,m;
struct node
{
int x,y,st,hx,hy;
node(){}
node(int _x,int _y,int _hx,int _hy,int _st):x(_x),y(_y),hx(_hx),hy(_hy),st(_st){}
};
bool jd(int x,int y)//判断位置是否合法
{
if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=1) return true;
return false;
}
bool find(node cur)//箱子是不是到洞里去啦
{
if(map[cur.x][cur.y]==3) return true;
return false;
}
void dfs(int x,int y,int a,int b)//搜索人能够到达的点
{
pvst[x][y]=1;
for(int i=0;i<4;++i){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(tx==a&&ty==b) continue;
if(jd(tx,ty)&&!pvst[tx][ty]) dfs(tx,ty,a,b);
}
}
int bfs(int x,int y,int px,int py)
{
queue<node> q;
node a,b;
q.push(node(x,y,px,py,0));
while(!q.empty()){
a=q.front();q.pop();
if(find(a)){
return a.st;
}
for(int i=0;i<4;++i){
memset(pvst,false,sizeof pvst);
dfs(a.hx,a.hy,a.x,a.y); //搜索人能到达的位置
b=a;
int pa=a.x+dir[(i+2)%4][0]; //箱子的后方,根据自己定义的方向,i取相应的加减
int pb=a.y+dir[(i+2)%4][1];
if(jd(pa,pb)&&pvst[pa][pb]){//人能到箱子的后面
b.x=a.x+dir[i][0];
b.y=a.y+dir[i][1];
if(jd(b.x,b.y)&&!vis[b.x][b.y][i]){//箱子的前面没有墙
b.hx=a.x;//吧人的位置变为原来箱子的位置
b.hy=a.y;
b.st++;//那我就推啦^-^
vis[b.x][b.y][i]=1; //标记状态
q.push(b);
}
}
}
}
return -1;
}
int main()
{
freopen("input.txt","r",stdin);
int t;
cin>>t;
while(t--){
scanf("%d%d",&n,&m);
int px,py,x,y;
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
scanf("%d",&map[i][j]);
if(map[i][j]==4){
px=i;
py=j;
}
if(map[i][j]==2){
x=i;
y=j;
}
}
}
memset(vis,false,sizeof vis);
printf("%d\n",bfs(x,y,px,py));
}
return 0;
}<span style="color:#009900;">
</span>