zoukankan      html  css  js  c++  java
  • BZOJ 1781 [Usaco2010 Feb]Ice 冰上

    BZOJ_1781

        这个题目如果Xi和Yi的范围都很小的话,那么就是个普通的广搜而已,但是现在Xi和Yi的范围超大,于是就多了各种离散化和二分查找。

        其实落脚点也就只有石头周围的4个点,和石头的数量是同级别的,这样每次枚举行走的方向时要快速的找到前面的第一个石头,用二分的话就可以实现比较快速的查找了。

        代码写的巨挫……而且因为代码长了之后就会有些恶心的小bug,找错找了很久,眼泪……

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define MAXD 20010
    #define INF 0x3f3f3f3f
    int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
    int N, B, dis[4 * MAXD], sx, sy, tx, ty;
    struct Point
    {
        int x, y;
        Point(){}
        Point(int _x, int _y) : x(_x), y(_y){}
        bool operator < (const Point &t) const
        {
            if(x == t.x) return y < t.y;
            return x < t.x;
        }
        bool operator == (const Point &t) const
        {
            return x == t.x && y == t.y;
        }
    }b[MAXD], p[4 * MAXD];
    void init()
    {
        int n = 0;
        scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
        for(int i = 0; i < B; i ++) scanf("%d%d", &b[i].x, &b[i].y);
        std::sort(b, b + B);
        std::unique(b, b + B);
        for(int i = 0; i < B; i ++)
            for(int j = 0; j < 4; j ++)
            {
                int x = b[i].x + dx[j], y = b[i].y + dy[j];
                int k = std::lower_bound(b, b + B, Point(x, y)) - b;
                if(k < B && b[k] == Point(x, y)) continue;
                p[n ++] = Point(x, y);
            }
        std::sort(p, p + n);
        N = std::unique(p, p + n) - p;
    }
    int xx[MAXD], X, yy[MAXD], Y;
    void solve()
    {
        for(int i = 0; i < B; i ++) xx[i] = b[i].x, yy[i] = b[i].y;
        std::sort(xx, xx + B), std::sort(yy, yy + B);
        X = std::unique(xx, xx + B) - xx, Y = std::unique(yy, yy + B) - yy;
        std::vector<int> xy[MAXD], yx[MAXD];
        for(int i = 0; i < B; i ++)
        {
            int x = std::lower_bound(xx, xx + X, b[i].x) - xx, y = std::lower_bound(yy, yy + Y, b[i].y) - yy;
            xy[x].push_back(b[i].y), yx[y].push_back(b[i].x);
        }
        for(int i = 0; i < B; i ++)
            std::sort(xy[i].begin(), xy[i].end()), std::sort(yx[i].begin(), yx[i].end());
        int sid = std::lower_bound(p, p + N, Point(sx, sy)) - p, tid = std::lower_bound(p, p + N, Point(tx, ty)) - p;
        std::queue<int> q;
        memset(dis, 0x3f, sizeof(dis[0]) * N);
        dis[sid] = 0;
        q.push(sid);
        while(!q.empty())
        {
            int id = q.front();
            q.pop();
            for(int i = 0; i < 4; i ++)
            {
                int x = p[id].x, y = p[id].y;
                int xid = std::lower_bound(xx, xx + X, x) - xx, yid = std::lower_bound(yy, yy + Y, y) - yy;
                if(i == 0)
                {
                    if(xid == X || xx[xid] != x) continue;
                    int yid = std::lower_bound(xy[xid].begin(), xy[xid].end(), y) - xy[xid].begin();
                    if(yid == xy[xid].size()) continue;
                    int nid = std::lower_bound(p, p + N, Point(xx[xid], xy[xid][yid] - 1)) - p;
                    if(dis[id] + 1 < dis[nid]) dis[nid] = dis[id] + 1, q.push(nid);
                }
                else if(i == 1)
                {
                    if(xid == X || xx[xid] != x) continue;
                    int yid = std::lower_bound(xy[xid].begin(), xy[xid].end(), y) - xy[xid].begin() - 1;
                    if(yid == -1) continue;
                    int nid = std::lower_bound(p, p + N, Point(xx[xid], xy[xid][yid] + 1)) - p;
                    if(dis[id] + 1 < dis[nid]) dis[nid] = dis[id] + 1, q.push(nid);
                }
                else if(i == 2)
                {
                    if(yid == Y || yy[yid] != y) continue;
                    int xid = std::lower_bound(yx[yid].begin(), yx[yid].end(), x) - yx[yid].begin();
                    if(xid == yx[yid].size()) continue;
                    int nid = std::lower_bound(p, p + N, Point(yx[yid][xid] - 1, yy[yid])) - p;
                    if(dis[id] + 1 < dis[nid]) dis[nid] = dis[id] + 1, q.push(nid);
                }
                else
                {
                    if(yid == Y || yy[yid] != y) continue;
                    int xid = std::lower_bound(yx[yid].begin(), yx[yid].end(), x) - yx[yid].begin() - 1;
                    if(xid == -1) continue;
                    int nid = std::lower_bound(p, p + N, Point(yx[yid][xid] + 1, yy[yid])) - p;
                    if(dis[id] + 1 < dis[nid]) dis[nid] = dis[id] + 1, q.push(nid);
                }
            }
        }
        printf("%d\n", dis[tid]);
    }
    int main()
    {
        while(scanf("%d", &B) == 1)
        {
            init();
            solve();
        }
        return 0;
    }

     

  • 相关阅读:
    linux内核中的crng是什么?
    linux内核中的hisi_sas是什么?
    linux内核中的brd是什么?
    内核中的xenfs是什么?
    linux内核中的cfq输入输出调度算法
    linux内核中的最简单的输入输出调度算法noop
    linux内核中侧async_tx是什么?
    linux内核中的fuse是什么?
    Executors.newSingleThreadScheduledExecutor();线程池中放入多个线程问题
    Executors.newSingleThreadScheduledExecutor() 问题
  • 原文地址:https://www.cnblogs.com/staginner/p/2740514.html
Copyright © 2011-2022 走看看