三分的多种写法及对应的精度 三分套三分原理
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\n%.5f\n%.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\n",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\n",r1,r2); 79 printf("%.2f\n",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\n",m,M); 78 printf("%.2f\n",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