推箱子 HDU1254
Posted bxd123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了推箱子 HDU1254相关的知识,希望对你有一定的参考价值。
较难的bfs
有两种方法做
一种双重bfs:
主bfs是箱子 还要通过dfs判断人是否能到箱子后面
用inmap函数的好处。。
箱子要用三位数组来标记 因为箱子可以回到原来到过的地方 因为推的方向不同 (第三位来表示方向)
并且地图无需改变(一些人在结构体里自带一份地图)
这题箱子的位置 对人来是是墙 不可越过 用设置vis2来实现 非常巧妙
用全局flag来代替dfs中的bool 方便很多 也不容易出错
#include<bits/stdc++.h> using namespace std; int n,m,m1[10][10],vis[10][10][4],vis2[10][10]; int sx,sy,ex,ey,rx1,ry1; int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0}; int flag=0; struct node { int x,y,d,rx,ry; node(int x=0,int y=0,int d=0,int rx=0,int ry=0):x(x),y(y),d(d),rx(rx),ry(ry){} }; bool inmap(int a,int b) { if(a<1||a>n||b<1||b>m||m1[a][b]==1) return false; return true; } void bfs1( int sx, int sy,int ex,int ey) { if(sx==ex&&sy==ey) {flag=1;return ;} if(flag==1)return;//值得学习 for(int i=0;i<4;i++) { if(vis2[sx+dx[i]][sy+dy[i]]==0&&inmap(sx+dx[i],sy+dy[i])) { //printf("%d %d ",sx+dx[i],sy+dy[i]); vis2[sx+dx[i]][sy+dy[i]]=1; bfs1(sx+dx[i],sy+dy[i],ex,ey); } } } void bfs() { memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); node u(sx,sy,0,rx1,ry1); queue<node>q; q.push(u); while(!q.empty()) { u=q.front();q.pop(); // printf("%d %d %d ",u.x,u.y,u.d); if(u.x==ex&&u.y==ey){printf("%d ",u.d);return;} for(int i=0;i<4;i++) { node v(u.x+dx[i],u.y+dy[i],u.d+1,u.rx,u.ry);//用自加是错的 if(inmap(u.x-dx[i],u.y-dy[i])&&inmap(v.x,v.y)&&vis[v.x][v.y][i]==0) { flag=0; memset(vis2,0,sizeof(vis2)); vis2[u.rx][u.ry]=1; vis2[u.x][u.y]=1;//非常关键!!!箱子也是障碍!!! bfs1(u.rx,u.ry,u.x-dx[i],u.y-dy[i]); if(flag) { vis[v.x][v.y][i]=1; v.rx=u.x-dx[i]; v.ry=u.y-dy[i]; q.push(v); } } } } printf("-1 ");return ; } int main() { int cas;scanf("%d",&cas); while(cas--) { scanf("%d%d",&n,&m); // printf("%d %d ",n,m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&m1[i][j]); if(m1[i][j]==3){ex=i;ey=j;} if(m1[i][j]==2){sx=i;sy=j;} if(m1[i][j]==4){rx1=i;ry1=j;} } // printf("%d %d ",sx,sy); bfs(); } return 0; }
还有一种方法是一次BFS 优先队列 用四维数组来标记人和箱子的座标 然后人疯狂乱走 如果人走到了箱子上了 就相当于推动了一次
#include<algorithm> #include<string.h> #include<stdio.h> #include<queue> using namespace std; int n,m; int f[4][2]={0,1,1,0,0,-1,-1,0}; int vis[9][9][9][9]; int mat[9][9]; struct node{ int x,y;//人坐标 int bx,by;//箱子坐标 int temp;//推箱子步数 bool friend operator<(const node &a, const node &b) {//必须优先队列,步数小优先 return a.temp>b.temp; } }start;//起点 void bfs() { node s,t; priority_queue<node>q; memset(vis,0,sizeof(vis)); vis[start.x][start.y][start.bx][start.by]=1; start.temp=0; q.push(start); while(!q.empty()) { t=q.top(); q.pop(); if(mat[t.bx][t.by]==3) {//终点 printf("%d ",t.temp); return; } for(int i=0;i<4;i++) { s.x=t.x+f[i][0];//人的下一步 s.y=t.y+f[i][1]; if(s.y>=1&&s.x>=1&&s.y<=m&&s.x<=n&&mat[s.x][s.y]!=1) { s.bx=t.bx;//不能推时,箱子的坐标 s.by=t.by; s.temp=t.temp; if(s.x==t.bx&&s.y==t.by) {//能推箱子 int tbx=t.bx+f[i][0]; int tby=t.by+f[i][1]; if(tbx>=1&&tbx<=n&&tby>=1&&tby<=m&&mat[tbx][tby]!=1) {//推完箱子判断是否过界,不过界,推数加1 s.bx=tbx;//更新箱子坐标 s.by=tby; s.temp++; } } if(!vis[s.x][s.y][s.bx][s.by]) { vis[s.x][s.y][s.bx][s.by]=1; q.push(s); } } } } printf("-1 "); return; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&mat[i][j]); if(mat[i][j]==4) { start.x=i;start.y=j; mat[i][j]=0; } if(mat[i][j]==2) { start.bx=i;start.by=j; mat[i][j]=0; } } } bfs(); } return 0; }
以上是关于推箱子 HDU1254的主要内容,如果未能解决你的问题,请参考以下文章