三分法(Ternary Search)求解凸(凹)函数的极值问题<题目篇>

前文解释了三分法求极值的方法及核心代码,而解决这类问题的重点就在于f函数的求得,比如HDU 2438,ZJU3203,PKU3301,Ural1874,lightoj1146/1240(解题报告)这些题目比较容易求出,但CodeForces185B是个例外,函数已经给出题意是给出a,b,c三个整数以及x,y,z和的最大值S,在x^a*y^b*z^c取得最大值时反求x,y,z的值,这种情况下我们可以在三分x的同时,三分y和z,求解时我们转化为求f=alnx+blny+clnz的最大值,同时要注意x,y,z等于0的情况,题目中已给出:ln(0)=-∞,同时此题要求精度较高,附菜鸟代码(听说此题可用某某函数得出一个很简单的结论,貌似前队友数学帝就是这么搞的= =。)

#include<stdio.h>
#include<math.h>
#define esp 1e-12
#define INF 99999999
int s,a,b,c;
double cal(double tem,int flag){
    double l=0,r=tem;
    while(r-l>esp){
      double temp1,temp2,temp3,temp4;
      double mid=(r+l)/2.0;
      double midmid=(r+mid)/2.0;
      if(mid==0) temp1=-INF;
      else temp1=log(mid);
      if(tem-mid==0) temp2=-INF;
      else temp2=log(tem-mid);
      if(midmid==0) temp3=-INF;
      else temp3=log(midmid);
      if(tem-midmid==0) temp4=-INF;
      else temp4=log(tem-midmid);
      if((b*temp1+c*temp2)-(b*temp3+c*temp4)>esp) r=midmid;
      else l=mid;
    }
    if(flag==1){
        printf("%0.10f %0.10f",l,tem-l);
        //return;
    }
    double temp5,temp6;
    if(l==0) temp5=-INF;
    else temp5=log(l);
    if(tem-l==0) temp6=-INF;
    else temp6=log(tem-l);
    return b*temp5+c*temp6;
}
void work(){
   double l=0,r=s;
   while(r-l>esp){
       double temp1,temp2;
       double mid=(r+l)/2.0;
       double midmid=(r+mid)/2.0;
       if(mid==0) temp1=-INF;
       else temp1=log(mid);
       if(midmid==0) temp2=-INF;
       else temp2=log(midmid);
       if((cal(s-mid,0)+a*temp1)-(cal(s-midmid,0)+a*temp2)>esp) r=midmid;
       else l=mid;
   }
   printf("%0.10f ",l);
   cal(s-l,1);
}
int main()
{
    scanf("%d%d%d%d",&s,&a,&b,&c);
    work();
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值