zoukankan      html  css  js  c++  java
  • P2208 [USACO13OPEN]重力异常What's Up With Gravity

    双端队列 + Hash判重广搜##

    首先看到这么复杂的地图第一反应就是广搜了,,,
    我觉得难点主要在

    1. 每次扩展的时候花费不一定增大(也就是说如果使用普通队列是不满足单调性的, 答案可能会偏大)
    2. 判重.

    第二点如果想偷懒可以直接用set搞定, 如果追求速度的话可以手写Hash函数.
    至于第一点嘛,,,我看有的人是用SPFA (@曹老师), 有的人是每次把当前相同花费的状态扩展完.
    如果扩展完的话, 不仅代码会变长, 而且细节繁琐. 所以在这里我使用了双端队列(deque) 来处理.
    对于当前状态扩展来的状态, 变化了重力的push_back, 其余的push_front, 这样就能解决队列单调性的问题了.

    #include <set>
    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef pair<int, int> P;
    const int MAXN = 5e2 + 10;
    
    int N, M;
    char mp[MAXN][MAXN];
    
    struct state
    {
        int x, y, val;
        bool g;//false->down, true-up;
    
        inline int Hash(){return ((x * 500 + y) << 1) | g;}
        inline int fall(){return x + (g ? -1 : 1);}
        inline bool out(){return !(1 <= x && x <= N && 1 <= y && y <= M);}
    
        void expand(vector<state> &cur){
            if(mp[fall()][y] != '#') {
                cur.push_back((state){fall(), y, val, g});
                return;
            }
            if(mp[x][y + 1] != '#') cur.push_back((state){x, y + 1, val, g});
            if(mp[x][y - 1] != '#') cur.push_back((state){x, y - 1, val, g});
            cur.push_back((state){x, y, val + 1, g ^ 1});
        }
    };
    
    bool vis[600000];
    deque<state> q;
    int bfs(){
        P s, t;
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= M; j++){
                if(mp[i][j] == 'C') s = P(i, j);
                if(mp[i][j] == 'D') t = P(i, j);
            }
        q.push_back((state){s.first, s.second, 0, false});
    
        while(!q.empty()){
            state u = q.front(); q.pop_front();
            if(u.out()) continue;
    
            vector<state> nxt; u.expand(nxt);
            for(vector<state>::iterator it = nxt.begin(); it != nxt.end(); ++it){
                if(P(it->x, it->y) == t) return it->val;
                if(vis[it->Hash()]) continue;
                
                vis[it->Hash()] = true;
                if(it->val > u.val) q.push_back(*it);
                else q.push_front(*it);
            }
        }
        return -1;
    }
    
    int main()
    {
        // freopen("p2208.in", "r", stdin);
        cin>>N>>M;
        for(int i = 1; i <= N; i++){
            scanf(" ");
            for(int j = 1; j <= M; j++)
                mp[i][j] = getchar();
        }
        cout<<bfs()<<endl;
        return 0;
    }
    
  • 相关阅读:
    阿里知识图谱首次曝光:每天千万级拦截量,亿级别全量智能审核
    LSTM简介以及数学推导(FULL BPTT)
    深度学习算法索引(持续更新)
    学界 | Yann LeCun新作,中日韩文本分类到底要用哪种编码?
    Android 常见内存泄漏的解决方式
    集成支付宝支付
    【4.29安恒杯】writeup
    sdut 3-7 类的友元函数的应用
    Linux下libsvm的安装及简单练习
    iOS 使用腾讯地图显示用户位置注意事项
  • 原文地址:https://www.cnblogs.com/wsmrxc/p/9592996.html
Copyright © 2011-2022 走看看