【洛谷P1126】机器人搬重物
题目大意:给定一个 N 行,M 列的地图,一个直径为 1.6 的圆形机器人需要从起点走到终点,每秒钟可以实现:向左转,向右转,向前 1-3 步。求从起点到终点最少要多长时间。
题解:相比于普通的走迷宫问题,这道题的物体有了体积,最佳的解决方式是选定一个参考点,比如只看这个有体积的机器人的左上角代表整个机器人,那么就不需要修改整个地图,且判断也会很方便。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=60;
const int inf=0x3f3f3f3f;
const int dx[]={-1,0,1,0};
const int dy[]={0,1,0,-1};
int n,m,stx,sty,edx,edy,direction;
int mp[maxn][maxn],d[maxn][maxn][4];
char s[2];
struct node{
int x,y,dir;
};
inline int getdir(char ch){
return ch=='N'?0:ch=='E'?1:ch=='S'?2:3;
}
void read_and_parse(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
scanf("%d%d%d%d%s",&stx,&sty,&edx,&edy,s);
direction=getdir(s[0]);
}
queue<node> q;
inline bool check(int x,int y){
if(mp[x][y]||mp[x+1][y]||mp[x][y+1]||mp[x+1][y+1])return 0;
if(x<=0||x>=n||y<=0||y>=m)return 0;
return 1;
}
int bfs(){
memset(d,0x3f,sizeof(d));
d[stx][sty][direction]=0,q.push(node{stx,sty,direction});
while(q.size()){
int x=q.front().x,y=q.front().y,dir=q.front().dir;q.pop();
if(x==edx&&y==edy)return d[edx][edy][dir];
for(int i=1;i<=3;i++){
int xx=x+dx[dir]*i,yy=y+dy[dir]*i;
if(!check(xx,yy))break;
if(d[xx][yy][dir]!=inf)continue;
d[xx][yy][dir]=d[x][y][dir]+1,q.push(node{xx,yy,dir});
}
if(d[x][y][(dir+1)%4]==inf)d[x][y][(dir+1)%4]=d[x][y][dir]+1,q.push(node{x,y,(dir+1)%4});
if(d[x][y][(dir+3)%4]==inf)d[x][y][(dir+3)%4]=d[x][y][dir]+1,q.push(node{x,y,(dir+3)%4});
}
return -1;
}
void solve(){
printf("%d\n",bfs());
}
int main(){
read_and_parse();
solve();
return 0;
}