代码自己写了一遍,有几个bug调不出,于是参考了这位大佬的题解:题解 P1126 【机器人搬重物】 - 林则徐 的博客 - 洛谷博客
然后顺利AC了。呜呜呜~先看题目吧!
思路很简单,就是BFS。
需要注意的几个点:
- 判重:这里我原本只考虑了x,y坐标,但是这样可能会漏解!这边采取的是线性方法。可以使不同的x y direct生成不同的hashr。int hashr(int x,int y,int direct){return direct*2700+x*50+y;}
- 碰撞检测:机器人走路每走一步都有可能碰到黑块,因此当他在同一方向上走一步遇到阻碍时,就不必走第二第三步了。
- 要求机器人完成任务所需的最少时间,我用了优先队列,将时间最短的点放在队首。
- 还有就是方向和转向的数学关系,这点可以大大缩减代码量,减少判断。
- case 'N':start.direct=0;break;
case 'E':start.direct=1;break;
case 'S':start.direct=2;break;
case 'W':start.direct=3;break; - int xd[4]={-1,0,1,0};
int yd[4]={0,1,0,-1};//分别是NESW,与1对应 - tmp=(cur.direct+4+1)%4;//右转 tmp=(cur.direct+4-1)%4;//左转
- case 'N':start.direct=0;break;
以上是我当时遇到的bug(优先队列可以不用,用不用都能ac)
#include<bits/stdc++.h>
using namespace std;
#define MAX 55
int n,m;
int g[MAX][MAX];
bool vis[50000]={0};
struct robot{
int x,y,t,direct;
//direct=0(north)1(east)2(south)3(west)
bool operator < (const robot r)const
{
return r.t<t;
}
}start,endr;
priority_queue <robot> q;
int xd[4]={-1,0,1,0};
int yd[4]={0,1,0,-1};
int hashr(int x,int y,int direct){return direct*2700+x*50+y;}
//优先队列,每次队首是时间最短的
int bfs()
{
while(!q.empty())
{
robot cur=q.top();
//cout<<"出队节点:x="<<cur.x<<"y="<<cur.y<<"时间:"<<cur.t<<"方向:"<<cur.direct<<endl;
q.pop();
if(cur.x==endr.x&&cur.y==endr.y)
{
return cur.t;
break;
}
int ha=hashr(cur.x,cur.y,cur.direct);
if(vis[ha])continue;
vis[ha]=1;
int tmp=(cur.direct+4-1)%4;//左转
q.push(robot{cur.x,cur.y,cur.t+1,tmp});
// cout<<"入队节点:x="<<cur.x<<"y="<<cur.y<<"时间:"<<cur.t+1<<"方向:"<<tmp<<endl;
tmp=(cur.direct+4+1)%4;//右转
q.push(robot{cur.x,cur.y,cur.t+1,tmp});
// cout<<"入队节点:x="<<cur.x<<"y="<<cur.y<<"时间:"<<cur.t+1<<"方向:"<<tmp<<endl;
//cout<<q.size();
int i=cur.direct;
for(int j=1;j<=3;j++)
{
int xn=cur.x+j*xd[i];
int yn=cur.y+j*yd[i];
//判断是否在边界,是否碰到黑点
if(0<xn&&xn<n&&0<yn&&yn<m&&!g[xn-1][yn-1]&&!g[xn-1][yn]&&!g[xn][yn-1]&&!g[xn][yn])
{
//将点存入队列
q.push(robot{xn,yn,cur.t+1,i});
//cout<<"入队节点:x="<<xn<<"yn="<<yn<<"时间:"<<cur.t+1<<"方向:"<<cur.direct<<endl;
}
else break;
}
//cout<<q.size();
}
return -1;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>g[i][j];
}
}
char c;
cin>>start.x>>start.y>>endr.x>>endr.y>>c;
switch(c)
{
case 'N':start.direct=0;break;
case 'E':start.direct=1;break;
case 'S':start.direct=2;break;
case 'W':start.direct=3;break;
}
start.t=0;
q.push(start);
cout<<bfs();
}