bzoj2765: [JLOI2010]铁人双项比赛

本文介绍了一道计算几何问题的解题思路与实现方法。通过构建直线方程来找到最优解对应的横坐标,使得特定条件下的目标函数达到最优,并提供了一份详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解

  这题思路好像不是那么明显。
  你可以列出每个人的用时关于k的式子
  

ti=(1v11v2)k+sv2

  那么你就要选择一个恰当的k使得tn最小且次小值与它的差最大。
  那就是说有若干条直线,你要找一个横坐标使得第n条直线在最下方,且次小的直线与它的差值最小。
  显然这样的横坐标肯定是某个交点的横坐标。因此我们可以求出所有的交点,然后每个交点检验一下它是不是在最下方的交点,然后再更新下答案就好了。
  这样是O(n3)

代码

//计算几何
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 233
#define eps 1e-8
using namespace std;
int N, tot;
double k[maxn], b[maxn], dy=-1e100, s, dx;
struct point{double x, y;}pt[maxn*maxn];
point jiao(int l1, int l2)
{
    point pt;
    if(fabs(k[l1]-k[l2])<eps)return (point){-1,-1};
    pt.x=(b[l1]-b[l2])/(k[l2]-k[l1]);
    pt.y=pt.x*k[l1]+b[l1];
    return pt;
}
void input()
{
    int i;
    double v1, v2;
    scanf("%lf%d",&s,&N);
    for(i=1;i<=N;i++)
    {
        scanf("%lf%lf",&v1,&v2);
        k[i]=1/v1-1/v2;
        b[i]=s/v2;
    }
}
void solve()
{
    int i, j;
    double t, x, y;
    for(i=1;i<=tot;i++)
    {
        x=pt[i].x, y=pt[i].y;
        if(x<0 or x>s)continue;
        for(j=1;j<N;j++)if(k[j]*x+b[j]<y-eps)break;
        if(j==N)
            if(y-k[N]*x-b[N]>dy)dy=y-k[N]*x-b[N], dx=x;
    }
}
int main()
{
    int i, j;
    input();
    for(i=1;i<N;i++)for(j=i+1;j<N;j++)pt[++tot]=jiao(i,j);
    for(i=1;i<=N;i++)pt[++tot]=(point){0,b[i]}, pt[++tot]=(point){s,k[i]*s+b[i]};
    solve();
    if(dy<-eps)printf("NO");
    else printf("%.2lf %.2lf %d",dx,s-dx,(int)(dy*3600+0.5));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值