HDU

来源:互联网 发布:c语言计算排列组合 编辑:程序博客网 时间:2024/06/05 17:19

点我看题

题意:n个人参加一个接力赛,跑道长度为L,每个人根据跑步时的心情的不同速度也不一样,bad mood时速度为s,good mood时速度为t,每个人至少跑d米,当满足所有人都在badmood下且花费的时间不超过w的情况下,如果所有人都以goodmood跑,至少要花费多少时间。

分析:参考的HDU 4128 Running relay (贪心+凸包优化)这篇博客

参考代码:

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define eps 1e-6const int maxn = 1e4+10;int n;double d,len,w;int sgn( double x){    if( x > eps)//x>0        return 1;    else if( x < -eps)//x==0        return -1;    else//x<0        return 0;}//x:s,y:t//用点的横纵坐标来记录runner的速度值struct Point{    double x,y;    Point(){}    Point( double xx, double yy)    {        x = xx;        y = yy;    }    Point operator - ( const Point &p)const    {        return Point(x-p.x,y-p.y);    }    double operator ^ ( const Point &p)const    {        return x*p.y-p.x*y;    }    bool operator < ( const Point &p)const    {        return sgn(x-p.x) < 0 || (sgn(x-p.x) == 0 && sgn(y-p.y) < 0);    }}p[maxn],tmp[maxn];double xmult( Point p1, Point p2, Point p3){    return (p2-p1)^(p3-p1);}//找凸包,返回节点数int SetConvex( Point p[], int n){    int top = 0;    if( n == 0)        return 0;    tmp[top++] = p[0];    if( n == 1)        return 1;    tmp[top++] = p[1];    for( int i = 2; i < n; i++)    {        while( top >= 2 && sgn(xmult(tmp[top-2],tmp[top-1],p[i])) <= 0)            top--;        tmp[top++] = p[i];    }    return top;}//三分double ternary( Point a, int l, int r){    double k = 1e30;    while( l <= r)    {        int lm = (2*l+r)/3;//l+(r-l)*1/3        int rm = (l+2*r)/3;//l+(r-l)*2/3        double ll = (a.y-tmp[lm].y)/(a.x-tmp[lm].x);        double rr = (a.y-tmp[rm].y)/(a.x-tmp[rm].x);        if( sgn(ll-rr) >= 0)        {            k = min(k,rr);            l = lm+1;        }        else        {            k = min(k,ll);            r = rm-1;        }    }    return a.y*len+(w-a.x*len)*k;}double work(){    if( sgn(len) < 0 || sgn(w) < 0)//不满足条件        return -1;    sort(p,p+n);    if( sgn(w-p[0].x*len) < 0)//badmood下跑的最快的runner都跑不及        return -1;    int j = 1;    for( int i = 0; i < n; i++)    {        if( sgn(p[i].y-p[j-1].y) >= 0)//goodmood下后面的速度小,不保存            continue;        p[j++] = p[i];//速度大,保存下来    }    n = j;    if( n == 1)        return p[0].y*len;    for( j = 0; j < n && sgn(w-p[j].x*len) >= 0; j++)//找出临界点        ;    int tot = j;//记录单个满足条件的数量    int sz = SetConvex(p+j,n-j);    double ans = 1e30;    for( int i = 0; i < tot; i++)    {        ans = min(ans,p[i].y*len);        ans = min(ans,ternary(p[i],0,sz-1));    }    return ans;}int main(){    int T;    scanf("%d",&T);    while( T--)    {        scanf("%d%lf%lf%lf",&n,&d,&len,&w);        double s,t;        double base = 0;//基础时间(也就是每个人都要跑的)        for( int i = 0; i < n; i++)        {            scanf("%lf%lf",&s,&t);            p[i].x = s;            p[i].y = t;            len -= d;            w -= p[i].x*d;            base += p[i].y*d;        }        double add = work();        if( sgn(add) < 0)            puts("No solution");        else            printf("%.2f\n",base+add);    }    return 0;}


原创粉丝点击