三分的解法

三分。。。

二分,是求单调区间的解,而三分是求二次函数的解。
尝试用二分,求出mid后,显然不行。
这是就需要三分。
在这里插入图片描述
三分法会将区间分成三份,这个我们都已经知道了。分成三份,自然需要两个端点。这两个端点各有一个值,我们分别叫做m1和m2。我们要求的是函数的最小值,所以我们要想极值逼近。
m1和m2的函数值和它们距离极值点的远近是有关系的。离极值点越近,函数值越小(也有可能越大)
我们要缩小区间范围,逼近极值点,三分法的精髓在于,每次通过比较两个值的大小,缩小三分之一的区间。直到最后区间的范围小于我们设置的阈值为止

  • 使用两个点将之分为三段:

midl = left + (right - left)/3;
midr= right - (right - left)/3;

  • 如果midl比midr更加靠近最值点,我们就令 right = midr- 1; 【舍弃远离的那一段】
  • 如果midr比midl更加靠近罪之颠,令left = midl + 1; 【舍弃远离的那一段】

链接:https://ac.nowcoder.com/acm/problem/20276?&headNav=acm
来源:牛客网

题目描述
在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间
输入描述:
输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By
第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy
第三行是3个整数,分别是P,Q,R
输出描述:
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
示例1
输入

0 0 0 100 100 0 100 100

2 2 1
输出
复制
136.60
备注:
对于100%的数据,1\le A_x,A_y,B_x,B_y,C_x,C_y,D_x,D_y\le10^31≤A
x,A y,B x,B y,C x,C y,D x,D y≤10 3。

我们算从A到D点的最短距离,那么明显的,我们考虑三分。

我们先三分出从A点到AB中的某个点X,作为出发点,然后,再三分出从X到CD的某个点Y,再从Y直接到D,这样,我们就可以求出最小的值了。

我们来看看,我们这样三分是否完备。

我们走的最短路线一共有四种情况,即是否走两条传送带。

如果我们不走AB传送带,那么,其实就相当于一开始我们从A点走到A点,再开始走

不走CD传送带,也就是相当于直接从X走到D点(两点之间线段最短,且速度相同,所以不走CD传送带的话,直接走到D是最短的)
题解

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define endl "\n"
#define INF 0x3f3f3f3f
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pri_que_less priority_queue<int,vector<int>,less<int> >
#define pri_que_greater priority_queue <int,vector<int>,greater<int> >
#define Debug(in) cout<<#in<<"="<<(in)<<endl
using namespace std;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll qpow(ll a,ll n,ll mod){ll ans=1,base=a%mod;while(n){if(n&1)ans=(ans*base)%mod;base=(base*base)%mod;n>>=1;}return ans;}
 
 
const double esp = 1e-8;
double ax, ay, bx, by, cx, cy, dx, dy;
double p, q, r;
double dis(double x1, double y1, double x2, double y2){
  return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
double tim(double x1, double y1, double x2, double y2){
    return dis(x1, y1, x2, y2) / r + dis(x2, y2, dx, dy) / q;
}
 
double th(double x, double y) {
    double lx = cx, ly = cy, rx = dx, ry = dy;
    while (dis(lx, ly, rx, ry) > esp) {
        double tx = (rx-lx)/3, ty = (ry-ly)/3;
        double lmx = lx+tx, lmy = ly+ty, rmx = rx-tx, rmy = ry-ty;
        double ansl = tim(x, y, lmx, lmy);
        double ansr = tim(x, y, rmx, rmy);
        if (ansr - ansl > esp) {
            rx = rmx;
            ry = rmy;
        } else {
            lx = lmx;
            ly = lmy;
        }
    }
    return tim(x, y, lx, ly);
}
 
int main() {
    cin >> ax >> ay >> bx >> by;
    cin >> cx >> cy >> dx >> dy;
    cin >> p >> q >> r;
    double lx = ax, ly = ay, rx = bx, ry = by;
    while (dis(lx, ly, rx, ry) > esp) {
        double tx = (rx-lx)/3, ty = (ry-ly)/3;
        double lmx = lx+tx, lmy = ly+ty, rmx = rx-tx, rmy = ry-ty;
        double ansl = th(lmx, lmy) + dis(ax, ay, lmx, lmy)/p;
        double ansr = th(rmx, rmy) + dis(ax, ay, rmx, rmy)/p;
        if (ansr - ansl > esp) {
            rx = rmx;
            ry = rmy;
        } else {
            lx = lmx;
            ly = lmy;
        }
    }
    double ans = th(lx, ly) + dis(ax, ay, lx, ly)/p;
    printf("%.2lf\n", ans);
 
    return 0;
}

01分数规划

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值