三分算法求最值

假如是一个凸型函数,如何寻找最值呢?

发现图中斜率是单调递减的,二分找到斜率为0的点?(似乎在这个图中,是可行的)

下面介绍一种普遍求凹凸型函数的做法——三分法

如图,mid=(left+right)/2,mmid=(mid+right)/2

如果,f(mid)< f(mmid),则[left,mid]可以被舍弃了,left=mid;

   else   ,则[mmid,right]可以被舍弃了,right=mmid;

直到最后剩下3个点,找出最值就行了

 //凹函数     
 ll l1=0,r1=l,mid,mmid;
        
        while(l1<r1-2)
        {
            mid=(l1+r1)/2;
            mmid=(mid+r1)/2;
            
            if(fun(mid)>fun(mmid))
                l1=mid;
            else r1=mmid;
        }
    mid=(l1+r1)/2;
    printf("%lld
",min(fun(mid),min(fun(l1),fun(r1))));    

题目链接

java代码,用C++写要注意超long long

 1 import java.math.BigDecimal;
 2 import java.util.Scanner;
 3 import java.util.HashMap;
 4 import java.math.BigInteger;
 5 public class Main{
 6     static BigInteger min2(BigInteger x,BigInteger y)
 7     {   
 8         if(x.compareTo(y)==1) return y;
 9         else return x;
10     }
11     static BigInteger[] d= new BigInteger[200005];
12     static BigInteger[] f= new BigInteger[200005];
13     static BigInteger[] pre= new BigInteger[200005];
14     static BigInteger[] suf= new BigInteger[200005];
15     static BigInteger a,b,m;
16     public static void main(String[] args) {
17         Scanner cin = new Scanner(System.in);
18         int l;
19         m=cin.nextBigInteger();
20         l=cin.nextInt();
21         pre[0]=BigInteger.valueOf(0);
22         for(int i=1;i<=l;i++)
23             {
24             d[i]=cin.nextBigInteger();
25             f[i]=cin.nextBigInteger();
26             pre[i]=pre[i-1].add(d[i].multiply(d[i]).multiply(f[i]));
27             }
28         suf[l+1]=BigInteger.valueOf(0);
29         for(int i=l;i>=1;i--)
30             {
31                 suf[i]=suf[i+1].add(m.multiply(f[i]));
32             }
33          
34         int q;
35         q=cin.nextInt();
36         while(q--!=0)
37         {
38              
39             a=cin.nextBigInteger();
40             b=cin.nextBigInteger();
41             int l1=0,r1=l,mid,mmid;
42             while(l1<r1-2)
43             {
44                 mid=(l1+r1)/2;
45                 mmid=(mid+r1)/2;
46                 if(a.multiply(pre[mid]).add(b.multiply(suf[mid+1])).compareTo(a.multiply(pre[mmid]).add(b.multiply(suf[mmid+1])))==1)
47                     l1=mid;
48                 else r1=mmid;
49             }
50             mid=(l1+r1)/2;
51             System.out.println(min2(a.multiply(pre[mid]).add(b.multiply(suf[mid+1])),min2(a.multiply(pre[l1]).add(b.multiply(suf[l1+1])),a.multiply(pre[r1]).add(b.multiply(suf[r1+1])))));
52              
53              
54         }
55     }        
56     
57                 
58                 
59 }
View Code
原文地址:https://www.cnblogs.com/lnu161403214/p/8994255.html