【bzoj3680】【JSOI2004】平衡点 / 吊打XXX (模拟退火)

刚学模拟退火板子,自己好菜。

 1 #include<ctime>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #define N 10004
 7 using namespace std;
 8 double n,w[N],now=1000000000000000ll;
 9 struct node
10 {
11     double xi;
12     double yi;
13     node(double x,double y):xi(x),yi(y){}
14     node(){}
15 }a[N],ans;
16 double dis(node x,node y)
17 {
18     return sqrt((x.xi-y.xi)*(x.xi-y.xi)+(x.yi-y.yi)*(x.yi-y.yi));
19 }
20 double work()
21 {
22     int jr=rand()%10000;
23     return (double)jr/10000.0;
24 }
25 double sol(node x)
26 {
27     double ret=0;
28     for(int i=1;i<=n;i++)
29     {
30         ret+=dis(x,a[i])*w[i];
31     }
32     if(ret<now)
33     {
34         ans=x;
35         now=ret;
36     }
37     return ret;
38 }
39 void sa()
40 {
41     double temp=100000;
42     node JR=ans;
43     while(temp>0.001)
44     {
45         node tmp;
46         tmp.xi=JR.xi+(work()*2-1)*temp;
47         tmp.yi=JR.yi+(work()*2-1)*temp;
48         double delta=sol(JR)-sol(tmp);
49         if(delta>0||exp(delta/temp)>work())
50         {
51             JR=tmp;
52         }
53         temp*=0.99;
54     }
55     for(int i=1;i<=1000;i++)
56     {
57         node tmp;
58         tmp.xi=ans.xi+(work()*2-1)*temp;
59         tmp.yi=ans.yi+(work()*2-1)*temp;
60         sol(tmp);
61     }
62 }
63 int main()
64 {
65     srand(20030714);
66     scanf("%lf",&n);
67     for(int i=1;i<=n;i++)
68     {
69         scanf("%lf%lf%lf",&a[i].xi,&a[i].yi,&w[i]);
70         ans.xi+=a[i].xi,ans.yi+=a[i].yi;
71     }
72     ans.xi/=n,ans.yi/=n;
73     sa();
74     printf("%.3lf %.3lf
",ans.xi,ans.yi);
75     return 0;
76 }
View Code
原文地址:https://www.cnblogs.com/stddddd/p/9999451.html