这题跟 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>
HDU 1254——推箱子
时间: 2024-11-05 12:29:05