解决单峰最值问题0.618法—hdu 4355
0.618法:
设f(x)在区间[x,y]上为单峰函数,可以使用0.618法实现求解最值问题,实质与二分法一样,只是更加精确。
题意:
在x轴上有n个点a1,a2,...ai,每个点有wi重量,求(a1-x)^3*w1+(a2-x)^3*w2+(a3-x)^3*w3...+(ai-x)^3*wi的最小值。
View Code
1 /* 2 6499620 2012-08-09 20:37:56 Accepted 4355 781MS 1276K 1439 B G++ hanker 3 0.618法 4 */ 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<cmath> 9 10 using namespace std; 11 const int MAX=50005; 12 const double s=0.618; 13 14 double card[MAX],val[MAX],sum,minx,maxx; 15 int n; 16 17 double Pow(double n) 18 { 19 return n*n*n; 20 } 21 double f(double pos) 22 { 23 int i; 24 double ans=0; 25 for(i=0;i<n;i++) 26 ans+=Pow(fabs(card[i]-pos))*val[i]; 27 28 return ans; 29 } 30 31 void solve() 32 { 33 double a,b,c,d,C,D; 34 double eps=1e-4; 35 a=minx;b=maxx;c=b-s*(b-a); 36 d=a+b-c; 37 C=f(c);D=f(d); 38 while(b-a>eps) 39 { 40 41 if(C>D) 42 { 43 a=c;c=d; 44 d=a+s*(b-a); 45 C=D; 46 D=f(d); 47 } 48 else 49 { 50 b=d;d=c; 51 c=b-s*(b-a); 52 D=C; 53 C=f(c); 54 } 55 } 56 sum=f((a+b)/2); 57 } 58 59 int main() 60 { 61 int t,i,k=1; 62 scanf("%d",&t); 63 while(t--) 64 { 65 sum=0; 66 maxx=-1000005; 67 minx=1000005; 68 scanf("%d",&n); 69 for(i=0;i<n;i++) 70 { 71 scanf("%lf %lf",&card[i],&val[i]); 72 if(minx>card[i]) 73 minx=card[i]; 74 if(maxx<card[i]) 75 maxx=card[i]; 76 } 77 solve(); 78 printf("Case #%d: %.lf\n",k++,sum); 79 } 80 return 0; 81 }