P1126 机器人搬重物

题意:有一个网格图,机器人只能顺着网格的格点走,开始的时候机器人在某一个网格的左上角点上,然后给出机器人初始时面朝的方向(东、南、西、北),然后给出终点(也是某一个网格的左上角点)的位置,然后让你求从机器人当前位置到终点最少需要多少秒。

其中机器人的操作有(分别都是花费1s):

  1. 向前走1步
  2. 向前走2步
  3. 向前走3步
  4. 左转
  5. 右转

注意点

  1. 机器人有体积(机器人再走的过程中不能碰到墙壁、墙角、以及网格边缘、沿着墙走)
  2. 机器人有多种操作,所以可能会以多种方式到达同一位置,这个时候需要取所有走法耗时最小的(不要忘了入队,让他去更新后续的更小的时间,#9测试点血的教训!!!
  3. NS互转,WE互转需要花费2s
  4. 机器人从当前方向O转到和O垂直的方向上需要花费1s

给你一个nxm网格(0~n-1,0~m-1),机器人能走的范围是(1~n-1,1~m-1)

思路:就按照格点来bfs,需要检查机器人走的下一步有没有挨到墙壁/墙角/网格边缘,又因为机器人可以走2、3步,所以需要检查机器人向前走的2、3步有没有挨到墙壁/墙角/网格边缘,如果碰到了,就说明不能走,不能入队,剩下的就是按照向上下左右来bfs了,只不过需要判断走的方向和当前方向来确定需要额外加多少的转弯时间

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;

const int N = 60;

int g[N][N];
int st[N][N];
int ti[N][N];
int p[26][26];
int n, m;

int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0};
char oris[] = {'W', 'E', 'N', 'S'};

struct node{
  int x, y;
  char ori;
};

int ax, ay;

queue<node> q;

int check(int k, int a, int b, int c, int d){
    if(c < 0 || d < 0 || c >= n || d >= m) return 1;
    if(g[c][d]) return 1;
    while(a != c || b != d){
        if(a <= 0 || b <= 0) return 1;
        if(g[a - 1][b - 1] || g[a][b] || g[a][b - 1] || g[a - 1][b])
            return 1;
        a += dx[k], b += dy[k];
    }
    return 0;
}


int bfs(node &s){
    q.push(s);
    
    memset(ti, 0x3f, sizeof ti);
    
    if(s.x == ax && s.y == ay) return 0;
    
    st[s.x][s.y] = 1;
    ti[s.x][s.y] = 0;

    while(q.size()){
        node h = q.front();
        q.pop();
        for(int j = 1; j <= 3; j ++){
            for(int i = 0; i < 4; i ++){
                int x = h.x + dx[i] * j, y = h.y + dy[i] * j;
                if(check(i, h.x, h.y, x, y)) continue;
                int nt = ti[h.x][h.y] + 1 + (p[oris[i] - 'A'][h.ori - 'A'] ? 2 : (oris[i] == h.ori ? 0 : 1 ));
                if(st[x][y]){
                    if(ti[x][y] > nt){
                        ti[x][y] = nt;
                        q.push({x, y, oris[i]});
                    }
                    continue;
                }
                st[x][y] = 1;
                ti[x][y] = nt;
                q.push({x, y, oris[i]});
                if(x == ax && y == ay) return ti[x][y];
            }
        }
    }
    
    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];
    
    p['N' - 'A']['S' - 'A'] = 1;
    p['S' - 'A']['N' - 'A'] = 1;
    p['E' - 'A']['W' - 'A'] = 1;
    p['W' - 'A']['E' - 'A'] = 1;
    
    node st;
    cin >> st.x >> st.y >> ax >> ay >> st.ori;
    
    cout << bfs(st);
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/15333618.html