繁华模拟赛 过河

Posted ACforever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了繁华模拟赛 过河相关的知识,希望对你有一定的参考价值。

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mkp make_pair
using namespace std;

const int MaxN = 255 * 255, MaxM = MaxN * 255, inf = 1000000000;
int N, M, x[MaxN], y[MaxN], W, Hash[255][255], To[255][255][255], indx[MaxN], indy[MaxN];
bool endp[MaxN];
struct Disk {
    int r, c;
    bool operator < (const Disk &a) const {
        if (r != a.r) return r < a.r;
        return c > a.c;
    }
}    d[MaxN], disk[MaxN];

ll sqr(ll x) { return x * x; }
ll GetDist(int i, int j) {
    return sqr(x[i] - x[j]) + sqr(y[i] - y[j]);
}

struct Node {
    int d, x;
    bool operator < (const Node &a) const {
        return d > a.d;
    }
    Node() {}
    Node(int d, int x) :d(d), x(x) {}
};

bool done[MaxN];
int dist[MaxN];
priority_queue <Node> Q;

int Dijkstra() {
    while (!Q.empty()) {
        int u = Q.top().x, i = indx[u], k = indy[u];
//        printf("%d %d\n", u, dist[u]);
        Q.pop();
        if (done[u]) continue;
        done[u] = 1;
        if (endp[u]) return dist[u];
        if (indy[u] != M) {
            int v = u + 1;
            if (dist[v] > dist[u] + disk[indy[v]].c - disk[indy[u]].c) {
                dist[v] = dist[u] + disk[indy[v]].c - disk[indy[u]].c;
                Q.push(Node(dist[v], v));
            }
        }
        for (int j = 1; j <= N; j++)
            if ((j != indx[u]) && (To[i][j][k] <= M)) {
                int v = Hash[j][To[i][j][k]];
                if (dist[v] > dist[u] + disk[To[i][j][k]].c) {
                    dist[v] = dist[u] + disk[To[i][j][k]].c;
                    Q.push(Node(dist[v], v));
                }
            }
    }
    return inf;
}

void Main() {
    int dtot;
    scanf("%d%d%d", &N, &dtot, &W);
    for (int i = 1; i <= N; i++) scanf("%d%d", x + i, y + i);
    for (int i = 1; i <= dtot; i++) {
        scanf("%d%d", &d[i].r, &d[i].c);
    }
    sort(d + 1, d + dtot + 1);
    M = 0;
    for (int i = 1; i <= dtot; i++) {
        while(M && (disk[M].c > d[i].c)) M--;
        disk[++M] = d[i];
    }

    int total = 0;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= M; j++) {
            Hash[i][j] = ++total;
            indx[total] = i;
            indy[total] = j;
        }

    Q = priority_queue <Node>();
    memset(done, 0, sizeof(done));
    memset(dist, 63, sizeof(dist));
    memset(endp, 0, sizeof(endp));
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (disk[j].r >= y[i]) {
                dist[Hash[i][j]] = disk[j].c;
                Q.push(Node(dist[Hash[i][j]], Hash[i][j]));
            }
            if (disk[j].r >= W - y[i]) endp[Hash[i][j]] = 1;
        }

        for (int j = 1; j <= N; j++)
            if (j != i) {
                ll dist = GetDist(i, j);
                int ind = M + 1;
                for (int k = 1; k <= M; k++) {
                    while ((ind > 1) && ((ll)(disk[k].r + disk[ind - 1].r) * (disk[k].r + disk[ind - 1].r) >= dist))
                        ind--;
                    To[i][j][k] = ind;
                }
            }
    }
    int ret = Dijkstra();
    if (ret < inf) printf("%d\n", ret);
    else printf("impossible\n");
}

int main()
{
    int T;
    freopen("river.in","r",stdin);
    freopen("river.out","w",stdout);
    scanf("%d", &T);
    while (T--) {
        Main();
    }
    return 0;
}

 

以上是关于繁华模拟赛 过河的主要内容,如果未能解决你的问题,请参考以下文章

繁华模拟赛 约会

繁华模拟赛 最优得分

繁华模拟赛 奇怪的棋

繁华模拟赛 Evensgn剪树枝

繁华模拟赛 Evensgn的债务

繁华模拟赛 Vincent的城堡