洛谷P1162【机器人搬重物】(BFS)

题目链接:P1126 机器人搬重物

这题WA了3次,第四次才AC,卡了卡了好几个小时

第一次:30分 第二次 :80分  第三次 90分  第四次100分

这题有个难处理的地方在于障碍物占了一个格子,而机器人只能走在格子的边线上,我们仍然把机器人按照正常的格子去走。

注意,题意给的是n*m个方格,也就是拥有(n+1)*(m+1)格点,这些格点是机器人可以走的。所以这里[0,n]这个区间机器人都是可以走的,但由于机器人的体积,0和n都不能走,因此区间变为开区间(0,n)

我们这样来处理一个有障碍物的方格,对于坐标为x,y的障碍物,我们认为它的左上部分(x-1,y),(x,y-1),(x-1,y-1)都是有障碍物的,即一个有障碍物的方格的四个点都标记为障碍,这与我们的格点是不矛盾的。

机器人走的是格点,而障碍物占据的确是一个方格,即为4个格点,我们按照坐标来读入障碍物,然后把障碍物的左上部分标记为障碍,这四个标记为障碍的格点即代表了这个障碍物(这里不理解的可以思考一下)

所以我们判断机器人下一步要走的格子能不能走不仅要判断(x,y)这个点是否为1,还要判断(x+1,y),(x,y+1),(x+1,y+1)这三个点是否为1,这里和我刚刚说的标记左上部分是并不矛盾的,因为(x,y)这个点属于这三个点左上部分,这三个点中任何一个点为1,都能导致(x,y)不能走,因为一个为障碍物的点左上部分被标记为障碍了,所以我们要判断4个点。

这样机器人有障碍物的位置关系就处理好了,下面还有要注意的地方,也就是我wa的原因

1:机器人每次可以走1步,2步,或者3步,我们按照1,2,3,的顺序进行bfs,如果当第一步或者第二步我们已经判断它不能走,那么我们就要break,举个例子说一下

比如说 0 0 1 0 0 0是我们读入的数据中的3个格点,机器人在左边黄色的0,机器人要往右走,我们首先判断第一步和第二步能不能走,显然第一步和第二步都有障碍不能走,但是第三步呢,却能走,所以这就出现了机器人跳过障碍物的情况,我们显然是不允许这样的,因此当我们判断第一步或者第二部有障碍的时候就break,注意是有障碍的时候才break,如果是vis数组标记过了导致不能走,我们不能break

2:要注意边界,由于机器人的体积,0和n都是不行的,

几次错误我都是往结构体加了一个vector来记录机器人的路径,才找到的错误的,这个方法挺不错的

#include<bits/stdc++.h>
using namespace std;
const int d[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };//朝向:0表示朝上 1下 2左 3右
const int r[4][2] = { { 2, 3 }, { 3, 2 }, { 1, 0 }, { 0, 1 } };//每个方向左右旋转变化后的方向
int n, m, a[55][55];
bool vis[55][55][4];
typedef pair<int, int> pp;
struct P{
    int x, y, f, t;
    //vector<pp> v;//这个可以记录路径
    P(int _x = 0, int _y = 0, int _f = 0, int _t = 0) :x(_x), y(_y), f(_f), t(_t){}
};
queue<P> que;
int sx, sy, gx, gy, sf;
char c;
bool valid(int x, int y)
{
    return x > 0 && y > 0 && x < n&&y < m&&a[x][y] != 1 && a[x + 1][y] != 1 && a[x][y + 1] != 1 && a[x + 1][y + 1] != 1;
}
void bfs()
{
    //vector<pp> sv;
    //sv.push_back(pp(sx, sy));
    que.push(P(sx, sy, sf, 0));
    vis[sx][sy][sf] = true;
    while (!que.empty())
    {
        P cur = que.front();
        que.pop();
        if (cur.x == gx&&cur.y == gy)
        {
            cout << cur.t << endl;
            return;
        }
        int x = cur.x, y = cur.y, f = cur.f, t = cur.t;
        //vector<pp> v = cur.v;
        for (int j = 1; j <= 3; j++)
        {
            int nx = x + d[f][0] * j, ny = y + d[f][1] * j;
            if (valid(nx, ny) && !vis[nx][ny][f])
            {
                vis[nx][ny][f] = true;
                //v.push_back(pp(nx, ny));
                que.push(P(nx, ny, f, t + 1));
                //v.pop_back();
            }
            else if (!valid(nx, ny))//注意
                break;
        }
        for (int i = 0; i < 2; i++)
        {
            if (!vis[x][y][r[f][i]])
            {
                vis[x][y][r[f][i]] = true;
                que.push(P(x, y, r[f][i], t + 1));
            }
        }
    }
    cout << -1;
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
        }
    }
    scanf("%d%d%d%d %c", &sx, &sy, &gx, &gy, &c);
    if (c == 'E') sf = 3;
    else if (c == 'W') sf = 2;
    else if (c == 'S') sf = 1;
    else sf = 0;
    bfs();
    return 0;
}

 

还有下面一种处理障碍的方法,和上面差不多,到时候我们可以直接判断a[x][y]!=2就是能走

  for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (a[i][j] == 1)
            {
                a[i][j] = a[i - 1][j] = a[i][j - 1] = a[i - 1][j - 1] = 2;//到时候我们可以直接判断a[x][y]!=2就是能走
            }
        }
    }

 

posted @ 2019-03-04 21:46  TLE自动机  阅读(208)  评论(0编辑  收藏  举报