bzoj3680模拟退火

看题意就是一道数学物理题,带权费马点   ——这怎么是数学了,这也是物理的

所以要用物理方法,比如FFF

国际著名oi选手miaom曾说

模拟退火初温可以低,但是最好烧个几千次

国际著名物理课代表+1曾说

miaom说什么都对

但是我瞎捣鼓了一波烧了一次不但A了还过了样例(不要说我递进的顺序不对),真是神奇

 1 #include<bits/stdc++.h>
 2 #define MAXN 10000
 3 #define EPS 1e-9
 4 using namespace std;
 5 int wt[MAXN+10],n,p,q;
 6 double x,y,ans;
 7 struct point{double x,y;}a[MAXN+10],now;
 8 double Rand(){    return 1.0*rand()/RAND_MAX;}
 9 double dist(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
10 double tot(const point p)
11 {
12     double sum=0;
13     for(int i=1;i<=n;i++)
14         sum+=dist(p,a[i])*wt[i];
15     return sum;
16 }
17 bool operator<(point a,point b){    return tot(a)<tot(b);}
18 point min(point a,point b){    return a<b?a:b;}
19 int main()
20 {
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++)
23         scanf("%d%d%d",&p,&q,&wt[i]),a[i]={(double)p,(double)q},x+=p,y+=q;
24     x/=n,y/=n;
25     now={x,y};
26     ans=tot(now);
27     double T=1000000;
28     while(T>EPS)
29     {
30         double dx=pow(T,2.0/3)*(1-2*Rand()),dy=pow(T,2.0/3)*(1-2*Rand());
31         point ok={now.x+dx,now.y+dy};
32         double tr=tot(ok);
33         double wrong=exp((ans-tr)/T*100);
34         if(wrong>Rand() || tr<ans)
35             ans=tr,now=ok;
36         T*=0.99;
37     }
38     printf("%.3lf %.3lf\n",now.x,now.y);
39 }

 

posted @ 2016-10-16 19:02  汪立超  阅读(277)  评论(0编辑  收藏  举报