1. 程式人生 > >「日常訓練」Watering Flowers(Codeforces Round #340 Div.2 C)

「日常訓練」Watering Flowers(Codeforces Round #340 Div.2 C)

題意與分析 (CodeForces 617C)

題意是這樣的:一個花圃中有若干花和兩個噴泉,你可以調節水的壓力使得兩個噴泉各自分別以\(r_1\)\(r_2\)為最遠距離向外噴水。你需要調整\(r_1,r_2\)的值使得所有的花都能被水所灌溉——換句話說,每一朵花要麼到第一個噴泉的距離不超過\(r_1\),要麼到第二個噴泉的距離不超過\(r_2\)。當然如果兩個條件都滿足也是可以的。你需要用盡可能少的水來實現以上要求,也就是說使得\(r_1^2+r_2^2\)儘可能的小。找出這個最小值。
那麼問題來了,這裡可能會有人YY出一個比較美好的\(O(n)\)的演算法:既然每個人都是不是取1就是取2,那麼我們遍歷一遍,每次遍歷選擇那個令半徑變大盡可能小的,那就完事了。但是並不可以,這樣會受到順序的制約,就是說不同順序的答案是不一樣的,不是正確的貪心。
那麼我們只能退而求其次:列舉每個點,硬點它的大小為第一個半徑,然後再列舉這\(n\)

個點,比它大的就歸第二個半徑,然後這樣一個\(n^2\)的演算法就能夠得到結果。
更好的是一個\(O(n\log n)\)的演算法。先排序(pair),然後維護一個倒序的與第二個噴泉的最大值。這樣,當我們迴圈到第\(i\)個的時候,如果採用第\(i\)個半徑,前\(i\)個一定能被覆蓋,只要保證剩下的被覆蓋就可以了——也就是取我們維護的那個最大值。這其實是上面那個美好的YY的變種。這裡就不贅述了。

程式碼

/*
 * Filename: cfr340d2c.cpp
 * Date: 2018-11-09
 */

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define PB emplace_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end()

#define QUICKIO                  \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)

using namespace std;
using pi=pair<int,int>;
using repType=int;
using ll=long long;
using ld=long double;
using ull=unsigned long long;

int
main()
{
QUICKIO
    ll n,x1,y1,x2,y2; cin>>n>>x1>>y1>>x2>>y2;
    vector<pi> vec;
    rep(i,1,n)
    {
        ll x,y; cin>>x>>y;
        vec.PB(x,y);
    }
    ll minans=9e17; 
    rep(i,0,n)
    {
        ll r12,r22=0;
        if(i==n)
            r12=0;
        else r12=(vec[i].fi-x1)*(vec[i].fi-x1)+(vec[i].se-y1)*(vec[i].se-y1);
        rep(j,0,n-1)
        {
            ll tmp1=(vec[j].fi-x1)*(vec[j].fi-x1)+(vec[j].se-y1)*(vec[j].se-y1);
            ll tmp2=(vec[j].fi-x2)*(vec[j].fi-x2)+(vec[j].se-y2)*(vec[j].se-y2);
            if(tmp1<=r12) continue;
            else
            {
                r22=max(tmp2, r22);
            }
        }
        //cout<<r12<<" "<<r22<<endl;
        minans=min(minans, r22+r12);
    }
    cout<<minans<<endl;

    return 0;
}