【洛谷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;
}
posted @ 2019-01-09 17:29  shellpicker  阅读(314)  评论(0编辑  收藏  举报