• luogu4011 孤岛营救问题 分层图


    关键词:分层图 状态压缩 最短路径

    分层图:现在要求从起点到终点的最优路线,但受到手里拿着哪些钥匙的影响,最优路线不单纯了。因此,决定一个节点、一条边的存在的数中应当增加一个手中拿有钥匙的状态。这样就相当于把一张图按拿有钥匙的状态数分出了很多层。

    状态压缩:手中拿有钥匙的状态可以压缩到一个整数中。

    最短路径:手中拿有钥匙的状态固定了,在分层图中我们就不再用得着走回头路了。这样就转化成了最短路径问题。

    #include <cstdio>
    #include <cassert>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const int MAX_X = 20, MAX_Y = 20, MAX_KEY = 20, MAX_S = 1 << 11, INF = 0x3f3f3f3f;
    int Dist[MAX_X][MAX_Y][MAX_S];
    int Key[MAX_X][MAX_Y];
    int Gate[MAX_X][MAX_Y][MAX_X][MAX_Y];
    int TotX, TotY;
    const int xNext[] = { 0,-1,0,0,1 }, yNext[] = { 0, 0,1,-1,0 };
    
    struct Queue
    {
        int xs[MAX_X*MAX_Y*MAX_S], ys[MAX_X*MAX_Y*MAX_S], ss[MAX_X*MAX_Y*MAX_S];
        int head, tail;
        Queue() { head = tail = 0; }
        void push(int x, int y, int s) { xs[tail] = x; ys[tail] = y; ss[tail] = s; tail++; }
        void pop() { head++; }
        bool empty() { return head == tail; }
        int frontX() { return xs[head]; }
        int frontY() { return ys[head]; }
        int frontS() { return ss[head]; }
    };
    
    int Bfs()
    {
        int ans = INF;
        static Queue q;
        Dist[1][1][Key[1][1]] = 0;
        q.push(1, 1, Key[1][1]);
        while (!q.empty())
        {
            int x = q.frontX(), y = q.frontY(), s = q.frontS();
            q.pop();
            Dist[x][y][s | Key[x][y]] = Dist[x][y][s];
            s |= Key[x][y];
            for (int p = 1; p <= 4; p++)
            {
                int x2 = x + xNext[p], y2 = y + yNext[p];
                if (x2 >= 1 && x2 <= TotX && y2 >= 1 && y2 <= TotY &&
                    Dist[x2][y2][s]==INF &&
                    (Gate[x][y][x2][y2] == -1 || s&(1 << Gate[x][y][x2][y2])))
                {
                    Dist[x2][y2][s] = Dist[x][y][s] + 1;
                    q.push(x2, y2, s);
                    if (x2 == TotX&&y2 == TotY)
                        ans = min(ans, Dist[x2][y2][s]);
                }
            }
        }
        return ans;
    }
    
    int main()
    {
    #ifdef _DEBUG
        freopen("c:\noi\source\input.txt", "r", stdin);
    #endif
        int totObs, totKeySort, x1, x2, y1, y2, gate, totKey, key;
        memset(Gate, -1, sizeof(Gate));
        memset(Dist, INF, sizeof(Dist));
        scanf("%d%d%d%d", &TotX, &TotY, &totKeySort, &totObs);
        while (totObs--)
        {
            scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &gate);
            Gate[x1][y1][x2][y2] = Gate[x2][y2][x1][y1] = gate;
        }
        scanf("%d", &totKey);
        while (totKey--)
        {
            scanf("%d%d%d", &x1, &y1, &key);
            if (key >= 32)
                printf("error
    ");
            Key[x1][y1] |= 1 << key;
        }
        int ans = Bfs();
        if (ans == INF)
            printf("-1
    ");
        else
            printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    Windows下图文详解PHP三种运行方式(php_mod、cgi、fastcgi)
    【强烈推荐】利用NAT、Host-Only双虚拟网卡,实现Virtual Box中CentOS6.3联网
    PHP批量清空删除指定文件夹内容
    MySQL收藏
    Eclipse快捷键与使用技巧总结
    “知乎网”技术方案初探
    PHP数组常用函数
    PHP常用字符串的操作函数
    Linux下,如何给PHP安装pdo_mysql扩展
    PHP二维数组排序(list_order)
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8446741.html
Copyright © 2020-2023  润新知