• 牛客寒假算法基础集训营6 G 迷宫2(01bfs)


    迷宫2

    题目大意:

    最小化修改的格子的数量,使得人物能从左上角走到右下角

    思路:

    在每一个位置上有改与不改两种选择,也就是 0 和 1 两种花费,要是花费最少,我们可以使用 01bfs 解决。

    01bfs 本质上就是贪心的思想,运用双端队列,将花费为 0 的从队首加入,花费为 1 的从队尾加入,这样每次出队的节点都是当前这一步的最优节点。

    在本题中需要记录更改的路径,因为每个节点只会被更新一次,那么我们记录其前驱节点,即可从终点逆推回去。

    队列中储存了当前点、上一点和修改次数,点的存储尽量采用 0-index 为标号的存储方式,易于存储且容易转为为二维坐标。以下使用了 deque<tuple<int, int, int>> 的结构作为队列,实际上,对于参数类型相同的情况,我们可以使用 array<int, 3> ,这样更加易于访问。

    还有一个问题是,我一直采用 vscode 编写代码,其中 __cplusplus 的值没有办法更新,一直显示为 199711L ,所以导致没有 #include<array>,没法找到关于 array 的构造函数,没有找到具体的命令行参数解决这个问题,现在就是编译运行没有任何问题,但是语法检查会带波浪线。

    Code:
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        const string ch = "LRUD";
        int T;
        cin >> T;
        while (T--) {
            int n, m;
            cin >> n >> m;
            vector<string> mp(n);
            for (int i = 0; i < n; i++) {
                cin >> mp[i];
            }
            
            vector<int> pre(n * m, -1), dis(n * m, -1);
            deque<tuple<int, int, int>> q; // 当前点 上一点 修改次数
            q.push_front(tuple<int, int, int>(0, -1, 0));
    
            while (!q.empty()) {
                auto now = q.front();
                q.pop_front();
    
                if (dis[get<0>(now)] != -1) { // 确保每个点只更新一次,即得到最优解。一个点最多进队4或8次。
                    continue;
                }
                dis[get<0>(now)] = get<2>(now);
                pre[get<0>(now)] = get<1>(now); // 只用记录到达每个点时的状态
    
                int nx = get<0>(now) / m, ny = get<0>(now) % m;
                for (int i = 0; i < 4; i++) {
                    int tx = nx + dir[i][0], ty = ny + dir[i][1];
                    int nxt = tx * m + ty;
                    if (tx < 0 || tx > n - 1 || ty < 0 || ty > m - 1)
                        continue;
                    if (ch[i] != mp[nx][ny]) {
                        q.push_back({nxt, get<0>(now), get<2>(now) + 1});
                    } else {
                        q.push_front({nxt, get<0>(now), get<2>(now)});
                    }
                }
            }
    
            cout << dis[n * m - 1] << "\n";
    
            int x = n - 1, y = m - 1;
            while (!(x == 0 && y == 0)) {
                int px = pre[x * m + y] / m, py = pre[x * m + y] % m;
    
                char td;
                for (int i = 0; i < 4; i++) {
                    int tx = px + dir[i][0], ty = py + dir[i][1];
                    if (tx == x && ty == y) {
                        td = ch[i];
                        break;
                    }
                }
    
                if (td != mp[px][py]) {
                    cout << px + 1 << " " << py + 1 << " " << td << "\n";
                }
                x = px, y = py;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    [转载]Dorado学习笔记
    [转载]dorado学习笔记(二)
    [转载]Struts+Spring+HibernateSSH整合实例
    [转载]Dorado中DataTable使用技巧汇总
    [转载]Struts+Spring+HibernateSSH整合实例
    JAVA基础知识复习面试笔试宝典
    [转载]Dorado中DataTable使用技巧汇总
    [转载]Dorado学习笔记
    IE网页中PNG格式图片无法显示的解决方法
    网络字节序和主机字节序
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/15949897.html
Copyright © 2020-2023  润新知