• 『题解』孤岛营救问题


    题目链接

    LuoGu P4011 孤岛营救问题

    LOJ #6121. 「网络流 24 题」孤岛营救问题

    题目简述

    一个 (n imes m) 的矩阵,每个单元位置用一个有序数对(行号,列号)表示。

    上下左右四个方向相邻的两个单元格之间存在一下情况:

    • 直接相连

    • 符合某种条件的情况下相连

    • 不相连

    其中某种条件分为 (p) 类要素,使一种条件成立的要素相同,不同条件成立的要素不同。

    初始位置为 ((1,1)) ,问如何以最少步数到达 ((n,m))

    解题思路

    数据范围这么友好,不暴力怎么对得起出题人呢??/jk

    考虑定义

    • 一个四维数组表示 ((x_1,y_1) o (x_2,y_2)) 是否符合条件相连通。

    • (vis[i][j][k]) 表示条件要素为 (k) 的情况下,((i,j)) 位置是否已经查找过。

    • (key[i][j]) 表示第 (key) 类要素需要在 ((i,j)) 单元获取。

    这里用用到状态压缩存储条件要素。(不会状压的请去睡觉)

    然后,然后就可以直接枚举 (DFS) 了。(不会 (DFS) 搜最短路径的请去睡觉)

    小小优化

    定义结构体记录单元(行号,列号,满足的条件,到该单元的最小花费),用队列存储(将路径记录下来),减少枚举数量。

    友情提示

    • 钥匙质量不错,不是一次性的woc

    • 钥匙做工不错,一个单元可以放多把钥匙woc

    • 初始点好像并没有说不能放钥匙woc

    • 输出 (-1) 赞~

    • (DFS) 不加 return 可以卡掉五个测试点。。。(然后 (debug) 了一下午)

    CODE

    /*
    
    Name: #6121. 「网络流 24 题」孤岛营救问题
    Solution: 最短路
       
    By Frather_
    
    */
    #include <iostream>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <set>
    // #include <map>
    #include <stack>
    #define ll long long
    #define InF 0x7fffffff
    #define kMax 10e5
    #define kMin -10e5
    #define kMod 998244353
    #define kMod2 19260817
    #define kMod3 19660813
    #define base 1331
    using namespace std;
    /*=========================================快读*/
    int read()
    {
        int x = 0, f = 1;
        char c = getchar();
        while (c < '0' || c > '9')
        {
            if (c == '-')
                f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + (c ^ 48);
            c = getchar();
        }
        return x * f;
    }
    /*=====================================定义变量*/
    int n, m, p;
    int k;
    int s;
    int map[20][20][20][20], key[20][20];
    struct node
    {
        int x, y;
        int key;
        int dis;
    };
    bool vis[20][20][1 << 11];
    queue<node> q;
    
    int dx[5] = {0, 1, -1, 0, 0};
    int dy[5] = {0, 0, 0, 1, -1};
    
    int ans = -1;
    /*===================================自定义函数*/
    void bfs()
    {
        q.push((node){1, 1, 0 | key[0][0], 0}); //初始化第一个位置
        vis[1][1][0 | key[1][1]] = true;
        while (!q.empty())
        {
            node now = q.front(), next;
            q.pop();
            for (int i = 1; i <= 4; i++)
            {
                next.x = now.x + dx[i];
                next.y = now.y + dy[i];
                if (next.x < 1 || next.x > n || next.y < 1 || next.y > m || !map[now.x][now.y][next.x][next.y]) //若dfs越界或者该两单元间不存在可通路(即有“一堵不可逾越的墙”),跳过
                    continue;
                if ((map[now.x][now.y][next.x][next.y] == -1) || (now.key & map[now.x][now.y][next.x][next.y]))
                {
                    if (!key[next.x][next.y])
                        next.key = now.key;
                    else
                        next.key = now.key | key[next.x][next.y];
                    if (vis[next.x][next.y][next.key])
                        continue;
                    vis[next.x][next.y][next.key] = true;
                    next.dis = now.dis + 1;
                    q.push(next);
                    if (next.x == n && next.y == m)
                    {
                        ans = next.dis;
                        return;
                    }
                }
            }
        }
    }
    /*=======================================主函数*/
    int main()
    {
        n = read();
        m = read();
        p = read();
        k = read();
        memset(map, -1, sizeof(map));
        for (int i = 1; i <= k; i++)
        {
            int x_1 = read();
            int y_1 = read();
            int x_2 = read();
            int y_2 = read();
            int g = read();
            map[x_1][y_1][x_2][y_2] = g ? 1 << g - 1 : g;
            map[x_2][y_2][x_1][y_1] = map[x_1][y_1][x_2][y_2];
        }
        s = read();
        for (int i = 1; i <= s; i++)
        {
            int x = read();
            int y = read();
            int g = read();
            key[x][y] |= 1 << g - 1;
        }
        bfs();
        printf("%d
    ", ans);
        return 0;
    }
    

    最后

    感谢阅读,留个点赞谢谢~

  • 相关阅读:
    两层或以上的showModalDialog解决方法
    我想学什么技术该怎样学
    中英文颜色代码参考
    来个实时更新文本框关于某个项的值
    JavaScript操作XML(一)
    关于css中的position在各大浏览器(IE,FireFox,Opera)中表现问题
    兼容IE/FF的手动触发事件的函数
    兼容各主浏览器透明的CSS
    判断浏览器类型的脚本
    Meta标签详解
  • 原文地址:https://www.cnblogs.com/Frather/p/14301072.html
Copyright © 2020-2023  润新知