1. 程式人生 > 實用技巧 >洛谷P1126《機器人搬重物》

洛谷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;
}