解决单峰最值问题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 }
posted @ 2012-08-09 20:59  hankers  阅读(757)  评论(0编辑  收藏  举报