
正文
洛谷 P1126 机器人搬重物 (BFS)
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
题目链接:https://www.luogu.org/problemnew/show/P1126
吐槽:这题很阴险
一开始没把格子图转化成点图:30分
转化成点图,发现样例过不去,原来每步要判断vis数组和step大小,寻找最优解,一块加了上去,以为能AX,结果边界处理不对:50分
加了边界后才AC。
(实际修改过程要坑爹的多orz 这么说吧,从20分到100分我全得过)
言归正传,搞一下这道题
广搜题,思路很好想:用结构体开个队列,分别保存每步的坐标、方向和步数,用vis数组保存当前格子上的最优解,然后开一个ans数组,保存所有能跑到终点的步数,搜完后,从ans中选一个最小的输出。
这是大致的思路,具体实现还有很多细节和坑点。
- 输入的格子图要转化成点图,即
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { bool a; cin>>a; if(a) { map[i][j]=1; map[i-1][j-1]=1; map[i-1][j]=1; map[i][j-1]=1; } }
- 要从点图的周围包上一层“1”,因为边界也是不能走的(多么痛的领悟QAQ)
for(int i=1;i<=n;i++){ map[n][i]=1; map[i][m]=1;}
- 要把答案存起来,找一个最小的输出(被我校dalao坑了 QAQ dalaoZZH:“广搜先找到的一定是最优解,所以把这句去了就行”)
if(q[h].x==ex&&q[h].y==ey) { ans[++tot]=q[h].st; } for(int i=1;i<=tot;i++) { if(ans[i]<minl) minl=ans[i]; }
- vis数组也要更新成最优解
if(vis[xx][yy]>step) { q[++t].x=xx, q[t].y=yy; q[t].st=step+1, q[t].dir=i; vis[xx][yy]=step; }
- 方向也要判断好
坑点差不多就这些了,接下来上代码
#include<iostream>#include<cstring>using namespace std;bool map[51][51]; //存地图int vis[51][51]; //存访问过的最优解struct yyy{ //队列 int x, //坐 y, //标 dir, //方向 st; //步数}q[5001];int h=1,t; //队头、队尾int ans[5001]={-1},tot,minl=0x7fffff; //处理答案int fx[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}}; //处理方向int main(){ //输入+预处理地图 int n,m; cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { bool a; cin>>a; if(a) { map[i][j]=1; map[i-1][j-1]=1; map[i-1][j]=1; map[i][j-1]=1; } } for(int i=1;i<=n;i++) { map[n][i]=1; map[i][m]=1; } int sx,sy,ex,ey; char sfx; cin>>sx>>sy>>ex>>ey>>sfx; //预处理搜索 q[++t].x=sx,q[t].y=sy,q[t].st=0; if(sfx=='E') q[t].dir=1; if(sfx=='W') q[t].dir=2; if(sfx=='S') q[t].dir=3; if(sfx=='N') q[t].dir=4; memset(vis,1,sizeof(vis)); //把vis数组初始化为一个很大的数,"1"实际为16843009(qwq) //搜索 while(h<=t) { if(q[h].x==ex&&q[h].y==ey) { ans[++tot]=q[h].st; } for(int i=1;i<=4;i++) //向四个方向搜索 { int step=q[h].st; if(i!=q[h].dir) //如果方向不一样,则需转弯,步数加一 { step=q[h].st+1; if((i==1&&q[h].dir==2)||(i==2&&q[h].dir==1)||(i==3&&q[h].dir==4)||(i==4&&q[h].dir==3)) //如果向后转,需要转两次弯 step=q[h].st+2; } for(int j=1;j<=3;j++) //枚举步数 { int xx,yy; xx=q[h].x+j*fx[i][0],yy=q[h].y+j*fx[i][1]; //xx、yy为目标点坐标 if(xx>n||xx<1||yy>m||yy<=0||map[xx][yy]) //如果越界或有障碍,直接退出循环 break; if(vis[xx][yy]>step) //保存最优解 { q[++t].x=xx, q[t].y=yy; q[t].st=step+1, q[t].dir=i; vis[xx][yy]=step; } } } h++; } for(int i=1;i<=tot;i++) //寻找最优答案 { if(ans[i]<minl) minl=ans[i]; } //输出 if(minl<0x7fffff) cout<<minl; else cout<<-1; return 0; //完美结束}
最后打个广告
我的洛谷博客
我的博客园博客








