zoukankan      html  css  js  c++  java
  • 洛谷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就是能走
                }
            }
        }
  • 相关阅读:
    使用IPTABLES限制IP上传下载速度,如何用iptables限速?
    基于queryperf 和 perftcpdns 的DNS压力测试
    搭建dnsmasq服务器,局域网内部解析
    Linux ipip隧道及实现
    使用FileZilla Server轻松搭建个人FTP服务器
    linux系统中如何查看日志 (常用命令)
    CentOS下安装XAMPP详细教程
    Tomcat中更改网站根目录
    php简单文件上传类
    SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
  • 原文地址:https://www.cnblogs.com/xiaoguapi/p/10471978.html
Copyright © 2011-2022 走看看