洛谷P1126《机器人搬重物》

原更新日期:2019-01-10 22:06:16

机器人有直径

题目描述

机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径\(1.6\)米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个\(N \times M\)的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动\(1\)步(Creep);向前移动\(2\)步(Walk);向前移动\(3\)步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为\(1\)秒。请你计算一下机器人完成任务所需的最少时间。

输入输出格式

输入格式

第一行为两个正整数\(N,M(N,M \le 50)\),下面\(N\)行是储藏室的构造,\(0\)表示无障碍,\(1\)表示有障碍,数字之间用一个空格隔开。接着一行有\(4\)个整数和\(1\)个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东\(E\),南\(S\),西\(W\),北\(N\)),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。

输出格式:
一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出\(−1\)

输入输出样例

输入样例

9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S

输出样例

12

解题思路

1. 将格子图转为点图 & 障碍物判断

要注意这个机器人是有直径的,所以边界和障碍物的四周都不能走

for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
        int ttt;
        scanf("%d", &ttt);
        if (ttt) {
            map[i][j] = map[i][j - 1] = map[i - 1][j] = map[i - 1][j - 1] = 1;
        }
    }
}

2.单向 BFS
枚举所有的步数和方向

3.三维数组判重
要注意本题是有方向的,所以vis数组需要开三维(vis[N][M][方向]

代码实现

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- External Headers -- */
#include <map>
#include <cmath>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)

namespace FastIO {
    
    inline int getint() {
        int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10 + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void putint(int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}


namespace Solution {
    const int dx[] = { 0, 1, 0, -1 };
    const int dy[] = { 1, 0, -1, 0 };
    const int MAXN_M = 50 + 10;
    
    struct Robot {
        int x, y;
        int dir;
        int step;
    };
    
    std::queue<Robot> q;
    
    bool vis[MAXN_M][MAXN_M][4];
    bool map[MAXN_M][MAXN_M];
    
    int n, m;
    int startx, starty, endx, endy, sd;
    
    char startdir;
}

signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
#endif
    using namespace Solution;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            int ttt;
            scanf("%d", &ttt);
            if (ttt) {
                map[i][j] = map[i][j - 1] = map[i - 1][j] = map[i - 1][j - 1] = 1;
            }
        }
    }
    scanf("%d %d %d %d %c", &startx, &starty, &endx, &endy, &startdir);
    switch(startdir) {
        case 'E': {
            sd = 0;
            break;
        }
        case 'S': {
            sd = 1;
            break;
        }
        case 'W': {
            sd = 2;
            break;
        }
        default: {
            sd = 3;
            break;
        }
    } // 对方向进行处理
    if (startx >= n || startx < 1 || starty >= m || starty < 1 || map[startx][starty]) {
        puts("-1");
        return 0;
    }
    Robot rb;
    rb.x = startx;
    rb.y = starty;
    rb.dir = sd;
    rb.step = 0;
    vis[startx][starty][sd] = true;
    q.push(rb);
    // 开始 BFS
    while (!q.empty()) {
        rb = q.front();
        q.pop();
        int newx = rb.x;
        int newy = rb.y;
        if (newx == endx && newy == endy) {
            printf("%d\n", rb.step);
            return 0;
        }
        // 枚举步数
        for (int steps = 1; steps <= 3; ++steps) {
            newx += dx[rb.dir];
            newy += dy[rb.dir];
            if (newx < 1 || newx >= n || newy < 1 || newy >= m || map[newx][newy]) {
                break;
            }
            if (!vis[newx][newy][rb.dir]) {
                vis[newx][newy][rb.dir] = true;
                Robot nown;
                nown.x = newx;
                nown.y = newy;
                nown.dir = rb.dir;
                nown.step = rb.step + 1;
                q.push(nown);
            }
        }
        // 更新步数
        Robot nown = rb;
        ++nown.step;
        --nown.dir;
        if (nown.dir == -1) nown.dir = 3;
        if (!vis[nown.x][nown.y][nown.dir]) {
            vis[nown.x][nown.y][nown.dir] = true;
            q.push(nown);
        }
        nown.dir = rb.dir + 1;
        if (nown.dir == 4) nown.dir = 0;
        if (!vis[nown.x][nown.y][nown.dir]) {
            vis[nown.x][nown.y][nown.dir] = true;
            q.push(nown);
        }
    }
    puts("-1");
    return 0;
}

posted @ 2020-10-14 18:26  Handwer  阅读(81)  评论(0编辑  收藏  举报