bzoj2765 [JLOI2010] Ironman Biathlon

Topic:
The Ironman Biathlon consists of long distance running and cycling.Now given the total distance s and the average speed of each runner's long run and cycling, you can find the k and r that are most favorable for a given runner.The so-called most favorable means that when this k and R are selected, the player can win the champion and lead the second place as much as possible.

Analysis:
It was long known that the solution to this problem was half-plane intersection.
In fact, we can easily get an equation:

We can think of it as a straight line with k as the x-axis and t as the y-axis
If we intersect these lines for 1..n-1, then the optimal solution must appear at the intersection.
So it's equivalent to uncarking these intersections with the line where n is located

So I started.
But it always feels a little troublesome, and it seems a little wrong.

Discovering code on the web, however, is surprisingly small
Actually: a smaller range of direct violence is fine
It seems like you can find the intersection point on the convex hull and then directly determine the point on the convex hull.
It seems that you can also directly find the intersection point with a half-plane intersection, and then judge

//Write a code snippet here
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>

using namespace std;

const double INF=1e13;
const int N=100010;
double a[N],b[N],s,pos,ans;
int n;
struct node{
    double x,y;
    node (double xx=0,double yy=0)
    {
        x=xx; y=yy;
    }
};
node p[N],q[N],po[N];

node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
node operator *(const node &a,const double &b){return node(a.x*b,a.y*b);}
node operator /(const node &a,const double &b){return node(a.x/b,a.y/b);}

double Dot(node a,node b){return a.x*b.x+a.y*b.y;}
double Len(node a){return sqrt(Dot(a,a));}
double Cross(node a,node b){return a.x*b.y-a.y*b.x;}

void solve(double x)
{
    if (x<0 || x>s) return;
    double ti=INF;
    for (int i=1;i<n;i++)
        ti=min(ti,a[i]*x+b[i]);
    ti-=a[n]*x+b[n];
    if (ti>ans) ans=ti,pos=x;
}

int main()
{
    scanf("%lf%d",&s,&n);
    for (int i=1;i<=n;i++)
    {
        double x,y;
        scanf("%lf%lf",&x,&y);
        a[i]=1.0/x-1.0/y;
        b[i]=s/y;
    }
    ans=-INF;   
    for (int i=1;i<n;i++)
        for (int j=i+1;j<n;j++)
            solve((b[j]-b[i])/(a[i]-a[j]));    //Intersection of two straight lines 
    solve(0.0);
    solve(s);
    if (ans>=0) printf("%.2lf %.2lf %.0lf\n",pos,s-pos,ans*3600);
    else printf("NO\n");
}

Posted on Sat, 18 Jul 2020 11:05:39 -0400 by defeated