看题意就是一道数学物理题,带权费马点 ——这怎么是数学了,这也是物理的
所以要用物理方法,比如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 ",now.x,now.y); 39 }