[JSOI2004]平衡点 / 吊打XXX

考虑模拟退火。

题目要我们找到一个点,使得整个系统平衡。

这个要求等价于让我们找到一个点,使得系统总能量最小。

我们退火出一个点,然后计算其能量即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstdlib>
 7 #include<cmath>
 8 #define N 10005
 9 using namespace std;
10 int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
15     return x*f;
16 }
17 struct node
18 {
19     int x,y,w;
20 }a[N];
21 int n;
22 double t,ansx,ansy,sx,sy,ans=1e18;
23 const double delta=0.993;
24 double calc(double x,double y)
25 {
26     double res=0;
27     for(int i=1;i<=n;i++)
28     {
29         double dtx=x-a[i].x,dty=y-a[i].y;
30         res+=sqrt((dtx*dtx)+(dty*dty))*a[i].w;
31     }
32     return res;
33 }
34 void SA()
35 {
36     double x=ansx,y=ansy;
37     t=2137;
38     while(t>1e-14)
39     {
40         double X=x+((rand()<<1)-RAND_MAX)*t;
41         double Y=y+((rand()<<1)-RAND_MAX)*t;
42         double now=calc(X,Y);
43         double D=now-ans;
44         if(D<0)
45         {
46             x=X;y=Y;
47             ansx=x;ansy=y;ans=now;
48         }
49         else if(exp(-D/t)*RAND_MAX>rand())x=X,y=Y;
50         t*=delta;
51     }
52 }
53 void solve()
54 {
55     ansx=(double)sx/n;ansy=(double)sy/n;
56     SA();
57     SA();
58     SA();
59     SA();SA();
60 }
61 int main()
62 {
63     srand(44042137);
64     n=read();
65     for(int i=1;i<=n;i++)
66     {
67         a[i].x=read();a[i].y=read();a[i].w=read();
68         sx+=a[i].x;sy+=a[i].y;
69     }
70     solve();
71     printf("%.3lf %.3lf\n",ansx,ansy);
72     return 0;
73 }
View Code

 

posted @ 2019-09-20 11:09  shao0320  阅读(147)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************