zoukankan      html  css  js  c++  java
  • Luogu 1979 [NOIP2013] 华容道

    要优先安排历年NOIP题

    考虑到要移动,肯定要先把空的格子移动到起点旁边,所以我们对于每一个询问都先bfs一次求出把空格移到起点的四个位置的最短路,而且要保证不能移动起点的方块。

    只有空的格子在一个格子四边的时候才可以进行一次移动,所以将一个可行的格子与它周围四个可能的空格出现位置捆绑为一个结点,这样通过移动空格或者把格子移到空格上都可以转移到下一个点。

    对于移动格子的边,只要扫一遍判一下合法就可以连上一条为1的边,剩下的可以采取预处理的策略先bfs一遍然后处理空格在一个格子四周移动时的最小位置,bfs的时候注意不能移动当前找到的格子。

    这样子一共最多有$n * n * 4 = 900$个点,每一个点搜一遍的时间上界是$n * n * 4 * n * n = O(n ^ {4})$级别的。

    对于每一个询问,只要先bfs一遍求出把空格移到起点四边的最短路线,然后丢到队列里跑个最短路就可以了。

    还是多写写堆dij吧,戒掉spfa

    这样子最后的答案就是终点四周的格子编号的最小值。

    注意到bfs函数可以重复利用。

    时间复杂度$O((nm)^{2} + q(nm)^{2})$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int L = 35;
    const int N = 3605;
    const int M = 1e6 + 5;
    const int inf = 0x3f3f3f3f;
    const int dx[] = {-1, 0, 1, 0};
    const int dy[] = {0, 1, 0, -1};
    
    int n, m, qn, tot, head[N], d[N], a[L][L], dis[L][L];
    bool vis[N];
    
    struct Edge {
        int to, nxt, val;
    } e[M];
    
    inline void add(int from, int to, int val) {
        e[++tot].to = to;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    struct Node {
        int x, y;    
        Node(int nowx = 0, int nowy = 0) : x(nowx), y(nowy) {}
        
        inline void readIn() {
            read(x), read(y);
        }
    };
    
    inline int id(Node now, int sta) {
        return ((now.x - 1) * m + now.y - 1) * 4 + sta + 1;
    }
    
    void bfs(Node st, Node ed, int sta) {
        queue <Node> Q; Q.push(st);
        memset(dis, 0, sizeof(dis)); dis[st.x][st.y] = 1;
        
        for(; !Q.empty(); ) {
            Node out = Q.front(); Q.pop();
            for(int i = 0; i < 4; i++) {
                Node in = Node(out.x + dx[i], out.y + dy[i]);
                if(!a[in.x][in.y] || (in.x == ed.x && in.y == ed.y) || dis[in.x][in.y]) continue;
                dis[in.x][in.y] = dis[out.x][out.y] + 1;
                Q.push(in);
            }
        }
        
        if(sta == 4) return;
        for(int i = 0; i < 4; i++) {
            int tox = ed.x + dx[i], toy = ed.y + dy[i];
            if((tox == st.x && toy == st.y) || !dis[tox][toy]) continue;
            add(id(ed, sta), id(ed, i), dis[tox][toy] - 1);
        }
        add(id(ed, sta), id(st, (sta + 2) % 4), 1);
    }
    
    void spfa(Node st, Node ed) {
        queue <int> Q;
        memset(d, 0x3f, sizeof(d));
        
        for(int i = 0; i < 4; i++) {
            int tox = st.x + dx[i], toy = st.y + dy[i];
            if(!dis[tox][toy]) continue;
            int now = id(st, i);
            Q.push(now);
            d[now] = dis[tox][toy] - 1;
            vis[now] = 1;
        }
        
        for(; !Q.empty(); ) {
            int x = Q.front(); Q.pop();
            vis[x] = 0;
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                if(d[y] > d[x] + e[i].val) {
                    d[y] = d[x] + e[i].val;
                    if(!vis[y]) {
                        vis[y] = 1;
                        Q.push(y);
                    }
                }
            }
        }
        
        int ans = inf;
        for(int i = 0; i < 4; i++) 
            ans = min(ans, d[id(ed, i)]);
        if(ans == inf) puts("-1");
        else printf("%d
    ", ans);
    } 
     
    int main() {
        read(n), read(m), read(qn);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                read(a[i][j]);
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++) {
                if(!a[i][j]) continue;
                for(int k = 0; k < 4; k++) {
                    int tox = i + dx[k], toy = j + dy[k];
                    if(a[tox][toy]) bfs(Node(tox, toy), Node(i, j), k);
                }
            }
        
        for(Node bla, st, ed; qn--; ) {
            bla.readIn(), st.readIn(), ed.readIn();
            if(st.x == ed.x && st.y == ed.y) {
                puts("0");
                continue;
            }
            bfs(bla, st, 4);
            spfa(st, ed);
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    mongodb添加延时节点
    AFNetworking 遇到错误 Code=-1016 "Request failed: unacceptable content-type: text/plain"
    使用cocoa捕获dock栏中的“退出”事件,解决qt开发的应用程序退出异常的问题
    【Grails 代理Proxy设置】部署Grails遇到Error Resolve error obtaining dependencies:错误,及解决方法
    【转】MongoDB 3.0 正式版本即将发布,强力推荐
    求数组的一个最大子数组
    MergeSort 归并排序(java)
    java查询几个菜单下的所有下级菜单
    InsertionSort 直接插入排序(java)
    sublime3配置java开发环境
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9511237.html
Copyright © 2011-2022 走看看