码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3291 [SCOI2016]妖怪

时间:2017-08-10 11:43:04      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:code   can   word   lin   clu   getc   tps   poi   char   

二次联通门 : luogu P3291 [SCOI2016]妖怪

 

 

 

 

/*
    luogu P3291 [SCOI2016]妖怪

    凸包
    
    我果然还是naive
    看见这题就想二分
    结果惨挂
    
    做了凸包后就想三分
    又挂了。。 
     
    完美落入了每个坑。。果然还是自己太菜
    
    对于每个妖怪,其在(a,b)时的最大战力为过当前点斜率为(-b/a)的直线的截距之和
    最大的战力就是最外面的那条直线
     
    对n个点做一个上凸包
    最大值一定在凸包的右上部分(自行脑补)
    
    那么这些点的斜率都有着一个范围ki-1<ki<ki+1
    
    那么战力就变为了一个双钩函数
    讨论求最值即可  
*/
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>

void read (long long &now)
{
    register char word = getchar ();
    int temp = 0;
    for (now = 0; !isdigit (word); word = getchar ())
        if (word == -)
            temp = 1;
    for (; isdigit (word); now = now * 10 + word - 0, word = getchar ());
    if (temp)
        now = -now;
}

#define INF 1e9

struct Point
{
    long long x, y;
    
    Point (long long __x, long long __y) : x (__x), y (__y) {}
    Point () {}
    
    bool operator < (const Point &now) const
    {
        return this->x == now.x ? this->y < now.y : this->x < now.x;
    }
    
    Point operator - (const Point &now) const
    {
        return Point (this->x - now.x, this->y - now.y);
    }
};

inline long long Cross (const Point &A, const Point &B)
{
    return A.x * B.y - A.y * B.x;
}

#define Max 1000250

inline double Calculate (const Point &now, const double &k)
{
    return k >= 0 ? INF : (double) now.x + now.y + - k * now.x - now.y / k;
}

inline double Get_point_k (const Point &now)
{
    return -sqrt ((double) now.y / now.x);
}

inline double Get_line_k (const Point &A, const Point &B)
{
    return (A.x ^ B.x) ? ((double)(A.y - B.y) / (double) (A.x - B.x)) : INF;
}

int Get_convex_Hull (Point *point, int N, Point *Stack)
{
    std :: sort (point + 1, point + N + 1);
    
    register int top = 0;
    for (int i = 1; i <= N; ++ i)
    {
        for (; top > 1 && Cross (Stack[top] - Stack[top - 1], point[i] - Stack[top - 1]) >= 0; -- top);
        Stack[++ top] = point[i];
    }
    return top;
}

Point yukari[Max], Stack[Max];

int main (int argc, char *argv[])
{
    register int i;
    int N;
    scanf ("%d", &N);
    for (i = 1; i <= N; ++ i)
        read (yukari[i].x), read (yukari[i].y);
    
    int M = Get_convex_Hull (yukari, N, Stack);
    
    if (M < 2)
    {
        printf ("%.4lf", Calculate (Stack[1], Get_point_k (Stack[1])));
        return 0;
    }
    double k, _k, __k, Answer = INF;
    
    k = Get_point_k (Stack[1]);
    __k = Get_line_k (Stack[1], Stack[2]);
    
    if (k >= __k)
        Answer = std :: min (Answer, Calculate (Stack[1], k));
    
    k = Get_point_k (Stack[M]);
    _k = Get_line_k (Stack[M - 1], Stack[M]);
    
    if (k <= _k)
        Answer = std :: min (Answer, Calculate (Stack[M], k));
    Answer = std :: min (Answer, Calculate (Stack[M], _k));
    
    for (i = 2; i < M; ++ i)
    {
        _k = Get_line_k (Stack[i - 1], Stack[i]);
        __k = Get_line_k (Stack[i], Stack[i + 1]);
        
        k = Get_point_k (Stack[i]);
        
        Answer = std :: min (Answer, Calculate (Stack[i], _k));
        if (k <= _k && k >= __k)
            Answer = std :: min (Answer, Calculate (Stack[i], k));
    }
    printf ("%.4lf", Answer);
    return 0;
}

 

luogu P3291 [SCOI2016]妖怪

标签:code   can   word   lin   clu   getc   tps   poi   char   

原文地址:http://www.cnblogs.com/ZlycerQan/p/7338091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!