bzoj 1857: [Scoi2010]传送带 三分套三分

题目

传送门

分析

恩NOIP快来了,作为一个没写过三分的弱菜,赶紧找一道三分题写一写,免得到时候写不出来。

三分法

对于一个上凸函数,若对于Ax,Bx(Ax < Bx),有Ay < By则峰顶必然在(Ax,+∞);若有Ay < By则峰顶必然在(-∞,Bx)中;若有Ay=By则峰顶必然在[Ax,Bx]中。
下凸函数同理。

回到这题,这题要我们在两条直线上分别求两个点,那么我们假设直线AB上取的点已经固定,那么在直线CD上取的点和A到D的距离一定是一个下凸函数(傻逼的我一开始还以为是上凸函数),那么我们就可以用三分法来求这个点。
但现在AB上的点不固定怎么办呢?同理我们也可以用三分法来求这个点,也就是所说的三分套三分。

一开始zz了,算时间居然用的是距离/速度~~感觉NOIP药丸啊!!!

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;

const double eps=1e-12;

struct pot{double x,y;}A,B,C,D;;
double P,Q,R;

double dis(pot a,pot b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double check(pot mid)
{
    pot l=C,r=D;
    while (dis(l,r)>=eps)
    {
        double w1=(r.x-l.x)/3,w2=(r.y-l.y)/3;
        pot mid1,mid2;
        mid1.x=l.x+w1;mid1.y=l.y+w2;
        mid2.x=r.x-w1;mid2.y=r.y-w2;
        double ans1=dis(A,mid)/P+dis(mid,mid1)/R+dis(mid1,D)/Q,ans2=dis(A,mid)/P+dis(mid,mid2)/R+dis(mid2,D)/Q;
        if (ans1>=ans2) l=mid1;
        if (ans1<=ans2) r=mid2;
    }
    return dis(A,mid)/P+dis(mid,l)/R+dis(l,D)/Q;
}

int main()
{
    scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
    scanf("%lf%lf%lf%lf",&C.x,&C.y,&D.x,&D.y);
    scanf("%lf%lf%lf",&P,&Q,&R);
    pot l=A,r=B;
    while (dis(l,r)>=eps)
    {
        double w1=(r.x-l.x)/3,w2=(r.y-l.y)/3;
        pot mid1,mid2;
        mid1.x=l.x+w1;mid1.y=l.y+w2;
        mid2.x=r.x-w1;mid2.y=r.y-w2;
        double ans1=check(mid1),ans2=check(mid2);
        if (ans1>=ans2) l=mid1;
        if (ans1<=ans2) r=mid2;
    }
    printf("%.2lf",check(l));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值