uva-1476 Error Curves 三分

这个题一开始想用二分,想了想,二分只能用于单调递增和单调递减的函数,对于上凸和下凸函数,例如二次函数,所以要用三分,之前没有用过,学了一下,

三分查找通常用来迅速确定最值。
二分查找所面向的搜索序列的要求是:具有单调性(不一定严格单调);没有单调性的序列不是使用二分查找。
与二分查找不同的是,三分法所面向的搜索序列的要求是:序列为一个凸性函数。通俗来讲,就是该序列必须有一个最大值(或最小值),在最大值(最小值)的左侧序列,必须满足不严格单调递增(递减),右侧序列必须满足不严格单调递减(递增)。如下图,表示一个有最大值的凸性函数
1、mid与midmid在最值的同一侧。由于凸性函数在最大值(最小值)任意一侧都具有单调性,因此,mid与midmid中,更大(小)的那个 数自然更为靠近最值。此时,我们远离最值的那个区间不可能包含最值,因此可以舍弃。
2、mid与midmid在最值的两侧。由于最值在中间的一个区间,因此我们舍弃一个区间后,并不会影响到最值



写一下三分的基本代码实现

void trichotomy(double L,double R)
{
   double m1,m2;
   while(L < R) //这里也可以直接跑for(int i = 0;i < 100;i++) 也能跑出来
   {
       m1 = L + (R - L) / 3;
       m2 = R - (R - L) / 3;
      if(f(m1) < f(m2))
      {
         R = m2 - 1e-6; //
      }
      {
         L = m1 + 1e-6; // 这个精度需要自己把握,有一些题,就卡的1e-9
      }
   }
   return (m1 + m2) / 2;
}

再说一下这个题吧,这个题,就是让你三分x,然后求一个最小值,

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <math.h>
#include <stack>
#include <utility>
#include <string>
#include <sstream>
#include <cstdlib>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000 + 10;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int n;
int a[maxn],b[maxn],c[maxn];
double judge(double x)
{
    double ans = -INF;
    for(int i = 0;i < n;i++)
    {
        ans = max(ans,a[i]*x*x + b[i]*x + c[i]);
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
      scanf("%d",&n);
      double ans = 0;
      for(int i = 0;i < n;i++)
      {
          scanf("%d%d%d",&a[i],&b[i],&c[i]);
      }
      double L = 0.0;double R = 1000.0;
      double cur;
      while(L < R)
      {
          double num1 = L + (R - L) / 3;
          double num2 = R - (R - L) / 3;
          if(judge(num1) < judge(num2))
          {
              R = num2 - 1e-9;
              cur = judge(num2);
          }
          else
          {
              L = num1 + 1e-9;
              cur = judge(num1);
          }
      }
      printf("%.4lf\n",cur);
    }
    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值