1 条题解

  • 0
    @ 2025-8-24 22:50:58

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar rui_er
    九万里风鹏正举

    搬运于2025-08-24 22:50:58,当前版本为作者最后更新于2023-10-04 20:47:19,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这题一看就不是计算几何,考虑区间 DP。

    设凸多边形的 nn 个顶点依次为 P1,P2,,PnP_1,P_2,\cdots,P_n

    fi,jf_{i,j}i<ji < j 时表示 Pi,Pi+1,,Pj1,PjP_i,P_{i+1},\cdots,P_{j-1},P_j 组成的多边形的直径的平方,在 i>ji > j 时表示 Pi,Pi+1,,Pn,P1,,Pj1,PjP_i,P_{i+1},\cdots,P_n,P_1,\cdots,P_{j-1},P_j 组成的多边形的直径的平方。容易得到转移方程:

    $$f_{i,j}=\max\{f_{i+1,j},f_{i,j-1},dis^2(P_i,P_j)\} $$

    其中下标均为模 nn 意义下。

    答案即为每一对能将多边形分为两个面积为正的部分的点 (Pi,Pj)(P_i,P_j) 中,fi,j+fj,if_{i,j}+f_{j,i} 的最小值。其中,(Pi,Pj)(P_i,P_j) 能将多边形分为两个面积为正的部分,当且仅当 Pi1,Pi,PjP_{i-1},P_i,P_j 不共线,且 Pi,Pi+1,PjP_i,P_{i+1},P_j 不共线,使用向量叉积计算即可。

    时间复杂度 O(n2)O(n^2)

    // Problem: T368391 [GDCPC2023] M-Computational Geometry
    // Contest: Luogu
    // URL: https://www.luogu.com.cn/problem/T368391?contestId=135929
    // Memory Limit: 1 MB
    // Time Limit: 4000 ms
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    //By: OIer rui_er
    #include <bits/stdc++.h>
    #define rep(x, y, z) for(ll x = (y); x <= (z); ++x)
    #define per(x, y, z) for(ll x = (y); x >= (z); --x)
    #define debug(format...) fprintf(stderr, format)
    #define fileIO(s) do {freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);} while(false)
    #define endl '\n'
    using namespace std;
    typedef long long ll;
    
    mt19937 rnd(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
    ll randint(ll L, ll R) {
        uniform_int_distribution<ll> dist(L, R);
        return dist(rnd);
    }
    
    template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
    template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
    
    const ll N = 5e3 + 5;
    
    ll T, n, x[N], y[N], diam[N][N];
    
    inline ll sq(ll x) {return x * x;}
    inline bool line(ll i, ll j, ll k) {
        ll v1x = x[i] - x[j], v1y = y[i] - y[j];
        ll v2x = x[i] - x[k], v2y = y[i] - y[k];
        return v1x * v2y - v2x * v1y == 0;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        for(cin >> T; T; --T) {
            cin >> n;
            rep(i, 0, n - 1) cin >> x[i] >> y[i];
            auto inc = [&](ll x) {return (x + 1) % n;};
            auto dec = [&](ll x) {return (x - 1 + n) % n;};
            rep(dt, 1, n - 1) {
                rep(L, 0, n - 1) {
                    ll R = (L + dt) % n;
                    diam[L][R] = max({diam[inc(L)][R], diam[L][dec(R)], sq(x[L] - x[R]) + sq(y[L] - y[R])});
                }
            }
            ll ans = numeric_limits<ll>::max();
            rep(i, 0, n - 1) {
                rep(j, 0, n - 1) {
                    if(!line(dec(i), i, j) && !line(i, inc(i), j)) {
                        chkmin(ans, diam[i][j] + diam[j][i]);
                    }
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    9114
    时间
    4000ms
    内存
    1024MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者