[ABC257D] Jumping Takahashi 2 题解

[ABC257D] Jumping Takahashi 2 Solution

更好的阅读体验戳此进入

题面

给定 $ n $ 个不共点的蹦床,第 $ i $ 个蹦床的位置为 $ (x_i, y_i) $,反弹力为 $ p_i $。存在整数 $ S $。定义能从第 $ i $ 个蹦床跳到第 $ j $ 个蹦床当且仅当 $ p_i \times S \ge \lvert x_i - x_j \rvert + \lvert y_i - y_j \rvert $。你需要钦定一个起点,使得可以从该蹦床抵达所有蹦床(可以多步),并最小化 $ S $,输出最小值。

Solution

不难发现问题可以转化为,我们要选择一个点,求使得这个点能够到达其它所有点的最大代价,然后求所有起点最大代价的最小值,这东西有点像全源最短路,且数据范围很小。于是不难想到一步转化,可以将原不等式转化为 $ S \ge \dfrac{\lvert x_i - x_j \rvert + \lvert y_i - y_j \rvert}{p_i} $,显然 $ S $ 存在单调性,所以自然可以令 $ S = \left\lceil \dfrac{\lvert x_i - x_j \rvert + \lvert y_i - y_j \rvert}{p_i} \right\rceil $。于是可以认为 $ i \rightarrow j $ 的边权即为这个,然后跑一遍 FLoyd,维护每个源点的最大值,最后取个最小值即可,复杂度 $ O(n^3) $。当然不用 Floyd,或者改用 bfs + 二分答案,都是可以做到 $ O(n^2 \log n) $ 的,不过意义不大。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

template < typename T = int >
inline T read(void);

int N;
struct Node{ll x, y, p;}nod[300];
ll dis[300][300];
ll ans(LONG_LONG_MAX);

int main(){
    N = read();
    for(int i = 1; i <= N; ++i)nod[i].x = read(), nod[i].y = read(), nod[i].p = read();
    for(int i = 1; i <= N; ++i)
        for(int j = 1; j <= N; ++j)
            if(i == j)dis[i][j] = 0;
            else
                dis[i][j] = (ll)ceil((ld)(abs(nod[i].x - nod[j].x) + abs(nod[i].y - nod[j].y)) / (ld)nod[i].p),
                dis[j][i] = (ll)ceil((ld)(abs(nod[i].x - nod[j].x) + abs(nod[i].y - nod[j].y)) / (ld)nod[j].p);
    for(int k = 1; k <= N; ++k)
        for(int i = 1; i <= N; ++i)
            for(int j = 1; j <= N; ++j)
                dis[i][j] = min(dis[i][j], max(dis[i][k], dis[k][j]));
    for(int s = 1; s <= N; ++s){
        ll mx(-1);
        for(int t = 1; t <= N; ++t)mx = max(mx, dis[s][t]);
        ans = min(ans, mx);
    }printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2022_12_09 初稿

posted @ 2023-01-07 15:41  Tsawke  阅读(38)  评论(0)    收藏  举报