1. 程式人生 > >BZOJ4570 [Scoi2016]妖怪

BZOJ4570 [Scoi2016]妖怪

gree sam ren time search 表示 abs ava table

題意

技術分享圖片
F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入門OJ ModifyUser autointLogout 捐贈本站
Problem 4570. -- [Scoi2016]妖怪

4570: [Scoi2016]妖怪

Time Limit: 10 Sec Memory Limit: 64 MB
Submit:
1251 Solved: 399
[Submit][Status][Discuss]

Description

邱老師是妖怪愛好者,他有n只妖怪,每只妖怪有攻擊力atk和防禦力dnf兩種屬性。邱老師立誌成為妖怪大師,於 是他從真新鎮出發,踏上未知的旅途,見識不同的風景。環境對妖怪的戰鬥力有很大影響,在某種環境中,妖怪可 以降低自己k×a點攻擊力,提升k×b點防禦力或者,提升自己k×a點攻擊力,降低k×b點防禦力,a,b屬於正實數 ,k為任意實數,但是atk和dnf必須始終非負。妖怪在環境(a,b)中的戰鬥力為妖怪在該種環境中能達到的最大攻擊 力和最大防禦力之和。strength(a,b)=max(atk(a,b))+max(dnf(a,b))環境由a,b兩個參數定義,a,b的含義見前 文描述。比如當前環境a=3,b=2,那麽攻擊力為6,防禦力為2的妖怪,能達到的最大攻擊力為9,最大防禦力為6。 所以該妖怪在a=3,b=2的環境下戰鬥力為15。因此,在不同的環境,戰鬥力最強的妖怪可能發生變化。作為一名優 秀的妖怪訓練師,邱老師想發掘每一只妖怪的最大潛力,他想知道在最為不利的情況下,他的n只妖怪能夠達到的 最強戰鬥力值,即存在一組正實數(a,b)使得n只妖怪在該環境下最強戰鬥力最低。

Input

第一行一個n,表示有n只妖怪。接下來n行,每行兩個整數atk和dnf,表示妖怪的攻擊力和防禦力。 1≤n≤10^6, 0<atk,dnf≤10^8

Output

輸出在最不利情況下最強妖怪的戰鬥力值,保留4位小數。

Sample Input

3
1 1
1 2
2 2

Sample Output

8.0000

HINT

Source

[Submit][Status][Discuss]
?
HOME Back
??? 中文 ????? English ???
版權所有 ?2008-2018 大視野在線測評 | 湘ICP備13009380號 Based on opensource project hustoj.

分析

參照Sky_miner的題解。

我們知道如果一個怪物要取到攻擊力的最大值,那麽一定是把防禦力都轉化了
所以我們可以把題目轉化成這個式子
\[\min(\max(atk + dnf + \frac{a}{b}dnf + \frac{b}{a}atk))\]
我們設\(k = -\frac{b}{a}\)
那麽上式變為了\[\min(\max(atk + dnf - (\frac{1}{k}dnf + k*atk)))\]
右側括號裏是對勾函數的形式,我們由數學知識得\(k = -\sqrt{\frac{dnf}{atk}}\)時取得最值

現在我們嘗試把所有怪物的屬性看成點映射到二維平面
設點\((x,y)\),假設通過了一條斜率為\(k(k < 0)\)的直線
我們通過計算發現這個直線的橫縱截距之和即為我們上面的計算式
而當\(k = -\sqrt{\frac{dnf}{atk}}\)橫縱截距之和最小
所以問題轉化成了為二維平面上的一些點確定一些平行線通過這些點使得最大的橫縱截距之和最小
我們知道最大的條直線一定是通過上凸殼上的點的
所以我們枚舉上凸殼上的點即可

時間復雜度\(O(n \log n)\)

代碼

operator*代替Dot,用operator/代替Cross,比較好寫。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;

co double eps=1e-8;
typedef struct Point {double x,y;}Vector;
Vector operator+(co Vector&a,co Vector&b) {return (Vector){a.x+b.x,a.y+b.y};}
Vector operator-(co Vector&a,co Vector&b) {return (Vector){a.x-b.x,a.y-b.y};}
double operator*(co Vector&a,co Vector&b) {return a.x*b.x+a.y*b.y;}
double operator/(co Vector&a,co Vector&b) {return a.x*b.y-a.y*b.x;}
double min_p(co Point&x) {return -sqrt(x.y/x.x);}
int dcmp(double x) {return fabs(x)<eps?0:(x<0?-1:1);}
double slope(co Point&a,co Point&b){
    if(dcmp(a.x)==0&&dcmp(a.y)==0) return 1e10;
    if(dcmp(b.x)==0&&dcmp(b.y)==0) return -1e10;
    if(dcmp(a.x-b.x)==0) return 1e10;
    return (b.y-a.y)/(b.x-a.x);
}
bool cmp(co Point&a,co Point&b) {return dcmp(a.x-b.x)==0?a.y<b.y:a.x<b.x;}
double calc(co Point&p,double k){
    if(k>=0) return 1e10;
    return p.x+p.y-k*p.x-p.y/k;
}
co int N=1e6+1;
Point p[N],ch[N];
int n,m;
void convex(){
    ch[m=1]=p[1];
    for(int i=2;i<=n;++i){
        while(m>1&&dcmp((ch[m]-ch[m-1])/(p[i]-ch[m]))>=0) --m;
        ch[++m]=p[i];
    }
    std::swap(n,m),std::swap(p,ch);
}

int main(){
//  freopen(".in","r",stdin),freopen(".out","w",stdout);
    read(n);
    for(int i=1;i<=n;++i) read(p[i].x),read(p[i].y);
    if(n==1) return printf("%.4lf\n",calc(p[1],min_p(p[1]))),0;
    std::sort(p+1,p+n+1,cmp),convex();
    double ans=1e10;
    double k1,k2,k;
    k2=slope(p[1],p[2]),  k=min_p(p[1]);if(k>=k2) ans=std::min(ans,calc(p[1],k));
    k1=slope(p[n-1],p[n]),k=min_p(p[n]);if(k<=k1) ans=std::min(ans,calc(p[n],k));
    ans=std::min(ans,calc(p[n],k1));
    for(int i=2;i<n;++i){
        k=min_p(p[i]),k1=slope(p[i-1],p[i]),k2=slope(p[i],p[i+1]);
        ans=std::min(ans,calc(p[i],k1));
        if(dcmp(k-k1)<=0&&dcmp(k-k2)>=0) ans=std::min(ans,calc(p[i],k));
    }
    printf("%.4lf\n",ans);
    return 0;
}

BZOJ4570 [Scoi2016]妖怪