HDU 1254 推箱子(BFS加优先队列)
Posted yinbiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1254 推箱子(BFS加优先队列)相关的知识,希望对你有一定的参考价值。
传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=1254
推箱子
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9942 Accepted Submission(s): 2920
现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.
从人为起点开始bfs,如果人走的下一步是箱子所在的坐标,说明找到了箱子,
箱子的坐标为当前所搜方向上人的坐标前进一格(就是推一格箱子,箱子前进的方向和人前进的方向是一致的),
判断箱子是否到达了目的地,如果是则输出箱子移动的最少步数,到不了就输出-1。
应该按照所走步数多少决定出队列顺序,所以用优先队列处理下。
(人从起点找箱子是不计数的)
需要注意的地方:
1.要判断人的位置是不是合法:有没有越界或者该位置是墙
2.要判断能不能推箱子:也就是人有没有找到箱子,比较一开始人和箱子是由距离的,
如果人走的下一步是箱子所在的坐标,说明找到了箱子
3.要判断箱子位置的合法性:越界或者该点是墙
具有做法:
先将箱子位置和人位置入队
1.如果箱子到了指定位置,直接输出步数
2.四个方向搜,先判断人的下一步位置是否合法,合法的话让人一直走,走到人能推箱子的时候
,在判断推导箱子之后箱子的位置合不合法,合法的话步数加1
具体请参考代码:
code:
#include<bits/stdc++.h> using namespace std; int dir[4][2]= {0,1,1,0,0,-1,-1,0}; //方向数组 #define max_v 12 int n,m; int G[max_v][max_v];//存图 int vis[max_v][max_v][max_v][max_v]; struct node { int x,y;//人的坐标 int bx,by;//箱子的坐标 int step;//推箱子的步数 bool friend operator<(const node &a, const node &b) { //必须优先队列,步数小优先ye1js return a.step>b.step; } } start; //起点 bool check_person(node next)//判断人的位置是否合法 { if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m&&G[next.x][next.y]!=1)//没有越界且不是墙 return true; else return false; } bool check_box1(node next,node t)//判断能不能推箱子 { if(next.x==t.bx&&next.y==t.by)//如果人走的下一步是箱子所在的坐标,说明找到了箱子 return true; else return false; } int check_box2(int tbx,int tby)//判断箱子坐标的合法性 { if(tbx>=1&&tbx<=n&&tby>=1&&tby<=m&&G[tbx][tby]!=1)//越界或者墙 return true; else return false; } void bfs() { node next,t; priority_queue<node>q; memset(vis,0,sizeof(vis));//标志位置空 //队列初始化 vis[start.x][start.y][start.bx][start.by]=1; start.step=0; q.push(start); while(!q.empty()) { t=q.top(); q.pop(); if(G[t.bx][t.by]==3)//箱子到了指定位置 { cout<<t.step<<endl; return ; } for(int i=0; i<4; i++) { next.x=t.x+dir[i][0];//人的下一步 next.y=t.y+dir[i][1]; if(check_person(next))//判断人的下一步位置是否合法 { next.bx=t.bx;//不能推箱子时,箱子的坐标 next.by=t.by; next.step=t.step; if(check_box1(next,t))//能推箱子 { int tbx=t.bx+dir[i][0];//推动箱子之后,箱子的坐标 int tby=t.by+dir[i][1]; if(check_box2(tbx,tby))//判断推导箱子之后箱子坐标的合法性,合法则更新坐标 { next.bx=tbx; next.by=tby; next.step++;//步数加1 } } if(vis[next.x][next.y][next.bx][next.by]==0)//该情况没有搜过,则入队,开始搜 { vis[next.x][next.y][next.bx][next.by]=1; q.push(next); } } } } cout<<"-1"<<endl; return ; } int main() { int t; cin>>t; while(t--) { cin>>n>>m; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { cin>>G[i][j]; if(G[i][j]==4) { start.x=i;//找到人在坐标 start.y=j; G[i][j]=0; } if(G[i][j]==2) { start.bx=i;//找到箱子的坐标 start.by=j; G[i][j]=0; } } } bfs(); } return 0; }
以上是关于HDU 1254 推箱子(BFS加优先队列)的主要内容,如果未能解决你的问题,请参考以下文章