zoukankan      html  css  js  c++  java
  • 三分的多种写法及对应的精度 三分套三分原理

    P.S.:

    while

    r-l>=minv1

    f(r)-f(l)>=minv2 better!!!

    =======================================

    https://www.luogu.org/problemnew/show/P3382

    正规三分法

    study from:

    https://blog.csdn.net/pi9nc/article/details/9666627

    f '(x)递减

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <time.h>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 #include <list>
    10 #include <stack>
    11 #include <queue>
    12 #include <vector>
    13 #include <bitset>
    14 #include <ext/rope>
    15 #include <algorithm>
    16 #include <iostream>
    17 using namespace std;
    18 #define ll long long
    19 #define minv 1e-6
    20 #define inf 1e9
    21 #define pi 3.1415926536
    22 #define E  2.7182818284
    23 const ll mod=1e9+7;//998244353
    24 const int maxn=1e2+10;
    25 
    26 int n;
    27 double a[maxn];
    28 
    29 double f(double x)
    30 {
    31     double v=0;
    32     int i;
    33     for (i=n;i>=0;i--)
    34         v=v*x+a[i];
    35     return v;
    36 }
    37 
    38 int main()
    39 {
    40     double l,r,m,mm;
    41     int i;
    42     scanf("%d%lf%lf",&n,&l,&r);
    43     for (i=n;i>=0;i--)
    44         scanf("%lf",&a[i]);
    45     while (r-l>=minv)
    46     {
    47         m=(l+r)/2;
    48         mm=(m+r)/2;
    49         if (f(m)>f(mm))
    50             r=mm;
    51         else
    52             l=m;
    53     }
    54     printf("%.5f",l);
    55     return 0;
    56 }

    f '(x)递增

     1 if (f(m)>f(mm)) 2 l=m; 3 else 4 r=mm;

    另外的写法

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <time.h>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 #include <list>
    10 #include <stack>
    11 #include <queue>
    12 #include <vector>
    13 #include <bitset>
    14 #include <ext/rope>
    15 #include <algorithm>
    16 #include <iostream>
    17 using namespace std;
    18 #define ll long long
    19 #define minv 1e-6
    20 #define inf 1e9
    21 #define pi 3.1415926536
    22 #define E  2.7182818284
    23 const ll mod=1e9+7;//998244353
    24 const int maxn=1e2+10;
    25 
    26 int n;
    27 double a[maxn];
    28 
    29 double f(double x)
    30 {
    31     double v=0;
    32     int i;
    33     for (i=n;i>=0;i--)
    34         v=v*x+a[i];
    35     return v;
    36 }
    37 
    38 int main()
    39 {
    40     double l,r,m,mm;
    41     int i;
    42     scanf("%d%lf%lf",&n,&l,&r);
    43     for (i=n;i>=0;i--)
    44         scanf("%lf",&a[i]);
    45     while (r-l>=minv)
    46     {
    47         m=(l+l+r)/3;
    48         mm=(l+r+r)/3;
    49         if (f(m)>f(mm))
    50             r=mm;
    51         else
    52             l=m;
    53     }
    54     printf("%.5f",l);
    55     return 0;
    56 }

    r-l缩减为原来的

    way1

    3/4

    1/2

    way2

    1/3

    1/3

    平均

    1/4(1-3/4)+1/2(1-1/2)>1/3+1/3

    最差

    1/3<1/2

    不太确定它们的精度是否有区别,网上也找不到类似的文章,个人倾向于区别不大。

    不同数据规模缩小的比较

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 
    11 const double eps=1e-8;
    12 const ll inf=1e9;
    13 const ll mod=1e9+7;
    14 const int maxn=1e5+10;
    15 
    16 
    17 
    18 int main()
    19 {
    20     int i;
    21     double j1=1,j2=1,j3=1,k1,k2,k3;
    22     k1=4.0/3;
    23     k2=3.0/2;
    24     k3=2;
    25     for (i=1;i<=50;i++)
    26         j1=j1*k1,j2=j2*k2,j3=j3*k3;
    27     printf("%.5f
    %.5f
    %.5f",j1,j2,j3);
    28     return 0;
    29 }
    30 /*
    31 10
    32 17.75773
    33 57.66504
    34 1024.00000
    35 
    36 50
    37 1765780.96326
    38 637621500.21405
    39 1125899906842624.00000
    40 
    41 100
    42 3117982410207.92578
    43 406561177535215232.00000
    44 1267650600228229401496703205376.00000
    45 */

    =========================================

    强烈不建议使用之后的方法,因为精度不够,

    同时,它们也能启发思路。

    某一位置的上升/下降情况

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <time.h>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 #include <list>
    10 #include <stack>
    11 #include <queue>
    12 #include <vector>
    13 #include <bitset>
    14 #include <ext/rope>
    15 #include <algorithm>
    16 #include <iostream>
    17 using namespace std;
    18 #define ll long long
    19 #define minv 1e-8
    20 #define inf 1e9
    21 #define pi 3.1415926536
    22 #define E  2.7182818284
    23 const ll mod=1e9+7;//998244353
    24 const int maxn=1e2+10;
    25 
    26 int n;
    27 double a[maxn]; //不能用int
    28 
    29 double f(double x)
    30 {
    31     double v=0;
    32     int i;
    33     for (i=n;i>=0;i--)
    34         v=v*x+a[i];
    35     return v;
    36 }
    37 
    38 int main()
    39 {
    40     int i;
    41     double l,r,m;
    42     cin>>n>>l>>r;
    43     ///用lf读入,用f输出
    44     for (i=n;i>=0;i--)
    45         scanf("%lf",&a[i]);
    46 //        cin>>a[i];
    47     while (r-l>=minv)
    48     {
    49         m=(l+r)/2;
    50         if (f(m-minv)<f(m+minv))
    51             l=m;
    52         else
    53             r=m;
    54     }
    55     printf("%.5f",l);
    56     return 0;
    57 }

    求导 递减 + -> -

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <time.h>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 #include <list>
    10 #include <stack>
    11 #include <queue>
    12 #include <vector>
    13 #include <bitset>
    14 #include <ext/rope>
    15 #include <algorithm>
    16 #include <iostream>
    17 using namespace std;
    18 #define ll long long
    19 #define minv 1e-6
    20 #define inf 1e9
    21 #define pi 3.1415926536
    22 #define E  2.7182818284
    23 const ll mod=1e9+7;//998244353
    24 const int maxn=1e2+10;
    25 
    26 //Çóµ¼ º¯Êý + -> -
    27 
    28 int n;
    29 double a[maxn];
    30 
    31 double f(double x)
    32 {
    33     double v=0;
    34     for (int i=n;i>=1;i--)
    35         v=v*x+a[i];
    36     return v;
    37 }
    38 
    39 int main()
    40 {
    41     int i;
    42     double l,r,m;
    43     cin>>n>>l>>r;
    44     for (i=n;i>=0;i--)
    45     {
    46         cin>>a[i];
    47         a[i]*=i;
    48     }
    49     while (r-l>minv)
    50     {
    51         m=(l+r)/2;
    52         if (f(m)>0)
    53             l=m;
    54         else
    55             r=m;
    56     }
    57     printf("%.5f",l);
    58     return 0;
    59 }

    ==================================

    三分套三分...的原理:

    f(x1,x2,...,xn)的最小值

    x1,x2,..,xn分别为系数

    前提:

    任意一维下,f''(xk)>0 [其它系数的值为任意值]

    证明:

    对于一组数值(a1,a2,...,an)

    对于任意的a2,...,an,根据f‘’(x1)>0,a1变为a1',其它系数不变,数值都是增加(减少/不变)了,这取决于f''(x1)下f(a1)和f(a1')的值。

    f''(x1)下f(a1)和f(a1')的关系,与x1=a1,x1=a2时,函数取得最小值的数值的关系 是一致的。

    在x1,...,xn-2系数确定时,

    在不同的xn-1系数中,求出了xn系数下的最小值,从而决定了在x1,...,xn-2系数下,xn-1系数为某个值时是最小的。

    在x1,...,xn-3系数确定时,

    在不同的xn-2系数中,求出了xn-1系数下(已经知道了x1,...,xn-1系数的值,唯一决定xn系数的值)的最小值,从而决定了在x1,...,xn-3系数下,xn-2,xn-1系数为某个值时是最小的。

    ……

    [大概那个意思,不好描述]

    而单独求每个系数的最优值(而其它系数任意选值)不可行,原因是不同的函数下(常数为0的项的数值发生变化),最优点的位置不同。

    题目:

    三分套三分套三分

    https://www.cnblogs.com/cmyg/p/9976329.html E题

    三分套三分

    http://acm.hdu.edu.cn/showproblem.php?pid=3400

    Sol:https://blog.csdn.net/u011787119/article/details/44598871

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <time.h>
     6 #include <string>
     7 #include <set>
     8 #include <map>
     9 #include <list>
    10 #include <stack>
    11 #include <queue>
    12 #include <vector>
    13 #include <bitset>
    14 #include <ext/rope>
    15 #include <algorithm>
    16 #include <iostream>
    17 using namespace std;
    18 #define ll long long
    19 #define minv 1e-6
    20 #define inf 1e9
    21 #define pi 3.1415926536
    22 #define E  2.7182818284
    23 const ll mod=1e9+7;//998244353
    24 const int maxn=1e5+10;
    25 
    26 double a,b,c,d,x,y,s,t;
    27 double p,q,v;
    28 double da,db,dx,dy;
    29 double l,r,L,R;
    30 double m,mm,M,MM;
    31 
    32 double F(double aa,double bb,double xx,double yy)
    33 {
    34     return sqrt(pow(aa-a,2)+pow(bb-b,2))/p+
    35         sqrt(pow(s-xx,2)+pow(t-yy,2))/q+
    36         sqrt(pow(aa-xx,2)+pow(bb-yy,2))/v;
    37 }
    38 
    39 double f(double aa,double bb)
    40 {
    41     L=0; R=1.0;
    42     while (R-L>minv)
    43     {
    44         M=(L+R)/2;
    45         MM=(M+R)/2;
    46         if (F(aa,bb,s+dx*M,t+dy*M)>F(aa,bb,s+dx*MM,t+dy*MM))
    47             L=M;
    48         else
    49             R=MM;
    50     }
    51     return F(aa,bb,s+dx*L,t+dy*L);
    52 }
    53 
    54 int main()
    55 {
    56     int T;
    57     scanf("%d",&T);
    58     while (T--)
    59     {
    60         scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
    61         scanf("%lf %lf %lf %lf",&x,&y,&s,&t);
    62         scanf("%lf %lf %lf",&p,&q,&v);
    63         da=c-a;
    64         db=d-b;
    65         dx=x-s;
    66         dy=y-t;
    67         l=0; r=1.0;
    68         while (r-l>minv)
    69         {
    70             m=(l+r)/2;
    71             mm=(m+r)/2;
    72             if (f(a+da*m,b+db*m)>f(a+da*mm,b+db*mm))
    73                 l=m;
    74             else
    75                 r=mm;
    76         }
    77         printf("%.2f
    ",F(a+da*m,b+db*m,s+dx*M,t+dy*M));
    78     }
    79     return 0;
    80 }

    实验证明单独求每个系数的最优值(而其它系数任意选值)不可行

    错误代码

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <time.h>
      6 #include <string>
      7 #include <set>
      8 #include <map>
      9 #include <list>
     10 #include <stack>
     11 #include <queue>
     12 #include <vector>
     13 #include <bitset>
     14 #include <ext/rope>
     15 #include <algorithm>
     16 #include <iostream>
     17 using namespace std;
     18 #define ll long long
     19 #define minv 1e-6
     20 #define inf 1e9
     21 #define pi 3.1415926536
     22 #define E  2.7182818284
     23 const ll mod=1e9+7;//998244353
     24 const int maxn=1e5+10;
     25 
     26 double a,b,c,d,x,y,s,t;
     27 double p,q,v;
     28 double da,db,dx,dy;
     29 double l,r,L,R;
     30 double m,mm,M,MM;
     31 
     32 double F(double aa,double bb,double xx,double yy)
     33 {
     34     return sqrt(pow(aa-a,2)+pow(bb-b,2))/p+
     35         sqrt(pow(s-xx,2)+pow(t-yy,2))/q+
     36         sqrt(pow(aa-xx,2)+pow(bb-yy,2))/v;
     37 }
     38 
     39 int main()
     40 {
     41     double r1,r2;
     42     int T;
     43     scanf("%d",&T);
     44     while (T--)
     45     {
     46         scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
     47         scanf("%lf %lf %lf %lf",&x,&y,&s,&t);
     48         scanf("%lf %lf %lf",&p,&q,&v);
     49         da=c-a;
     50         db=d-b;
     51         dx=s-x;
     52         dy=t-y;
     53 
     54         l=0; r=1.0;
     55         while (r-l>1e-15)///da,db*minv<...
     56         {
     57             m=(l+r)/2;
     58             mm=(m+r)/2;
     59             if (F(a+da*m,b+db*m,x,y)>F(a+da*mm,b+db*mm,x,y))
     60                 l=m;
     61             else
     62                 r=mm;
     63         }
     64         r1=m;
     65 
     66         l=0; r=1.0;
     67         while (r-l>1e-15)///dx,dy*minv<...
     68         {
     69             m=(l+r)/2;
     70             mm=(m+r)/2;
     71             if (F(a+da*r1,b+db*r1,x+dx*m,y+dy*m)>F(a+da*r1,b+db*r1,x+dx*mm,y+dy*mm))
     72                 l=m;
     73             else
     74                 r=mm;
     75         }
     76         r2=m;
     77 
     78 //        printf("%.5f %.5f
    ",r1,r2);
     79         printf("%.2f
    ",F(a+da*r1,b+db*r1,x+dx*r2,y+dy*r2));
     80     }
     81     return 0;
     82 }
     83 /*
     84 1
     85 0 1 2 3
     86 4 5 6 7
     87 100
     88 
     89 0 0 0 100
     90 100 0 100 100
     91 2 2 1
     92 
     93 0 1 2 3
     94 4 5 6 7
     95 10 5 3
     96 
     97 0 0 10 0
     98 20 0 20 20
     99 2 3 2
    100 0.26668 0.77516
    101 */

    正确代码

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <time.h>
      6 #include <string>
      7 #include <set>
      8 #include <map>
      9 #include <list>
     10 #include <stack>
     11 #include <queue>
     12 #include <vector>
     13 #include <bitset>
     14 #include <ext/rope>
     15 #include <algorithm>
     16 #include <iostream>
     17 using namespace std;
     18 #define ll long long
     19 #define minv 1e-6
     20 #define inf 1e9
     21 #define pi 3.1415926536
     22 #define E  2.7182818284
     23 const ll mod=1e9+7;//998244353
     24 const int maxn=1e5+10;
     25 
     26 double a,b,c,d,x,y,s,t;
     27 double p,q,v;
     28 double da,db,dx,dy;
     29 double l,r,L,R;
     30 double m,mm,M,MM;
     31 
     32 double F(double aa,double bb,double xx,double yy)
     33 {
     34     return sqrt(pow(aa-a,2)+pow(bb-b,2))/p+
     35         sqrt(pow(s-xx,2)+pow(t-yy,2))/q+
     36         sqrt(pow(aa-xx,2)+pow(bb-yy,2))/v;
     37 }
     38 
     39 double f(double aa,double bb)
     40 {
     41     L=0; R=1.0;
     42     while (R-L>minv)
     43     {
     44         M=(L+R)/2;
     45         MM=(M+R)/2;
     46         if (F(aa,bb,s+dx*M,t+dy*M)>F(aa,bb,s+dx*MM,t+dy*MM))
     47             L=M;
     48         else
     49             R=MM;
     50     }
     51     return F(aa,bb,s+dx*L,t+dy*L);
     52 }
     53 
     54 int main()
     55 {
     56     int T;
     57     scanf("%d",&T);
     58     while (T--)
     59     {
     60         scanf("%lf %lf %lf %lf",&a,&b,&c,&d);
     61         scanf("%lf %lf %lf %lf",&x,&y,&s,&t);
     62         scanf("%lf %lf %lf",&p,&q,&v);
     63         da=c-a;
     64         db=d-b;
     65         dx=x-s;
     66         dy=y-t;
     67         l=0; r=1.0;
     68         while (r-l>minv)
     69         {
     70             m=(l+r)/2;
     71             mm=(m+r)/2;
     72             if (f(a+da*m,b+db*m)>f(a+da*mm,b+db*mm))
     73                 l=m;
     74             else
     75                 r=mm;
     76         }
     77         printf("%.5f %.5f
    ",m,M);
     78         printf("%.2f
    ",F(a+da*m,b+db*m,s+dx*M,t+dy*M));
     79     }
     80     return 0;
     81 }
     82 /*
     83 100
     84 
     85 0 0 0 100
     86 100 0 100 100
     87 2 2 1
     88 
     89 0 1 2 3
     90 4 5 6 7
     91 10 5 3
     92 
     93 0 0 10 0
     94 20 0 20 20
     95 2 3 2
     96 0.00000 0.10557
     97 
     98 0 0 10 0
     99 20 0 20 20
    100 5 5 3
    101 1.00000 0.62500
    102 */

    http://acm.hdu.edu.cn/showproblem.php?pid=4717

    Sol:https://www.cnblogs.com/crazyapple/p/3315633.html

    多个二次函数的最大值是三分函数的证明

    https://www.cnblogs.com/cmyg/p/9784683.html

  • 相关阅读:
    k3sk8s集群-node节点设置不可调度或者删除node节点
    CentOS8防暴力破解fail2ban
    网站挂马情况处理
    linux给普通用户赋予sudo权限免密码
    Mockito (二十四)
    Mockito (二十三)
    Mockito (二十二)
    Mockito (二十一)
    Mockito (二十)
    Mockito (十九)
  • 原文地址:https://www.cnblogs.com/cmyg/p/9554220.html
Copyright © 2011-2022 走看看