经典物理模型…
资料详见http://bakser.blog.163.com/blog/static/23589413220147161124294/
我用的是模拟退火(参考的是http://www.mamicode.com/info-detail-213016.html).
大概做法:
1.取所有点横、纵坐标的平均值做为起始点(如果是随机数据目测可以起到很好的效果).
2.以当前点为圆心,半径r画圆,在圆内随机取一点作为新点(r为参数),然后模拟退火就可以了.
AC code:
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
typedef double llf;
const int N=10010;
int n;
int x[N],y[N],g[N];
llf cal(llf X,llf Y){
llf sum=0;
for(int i=1;i<=n;i++) sum+=(llf)sqrt((X-x[i])*(X-x[i])+(Y-y[i])*(Y-y[i]))*g[i];
return sum;
}
llf move(llf t){
llf flg=(rand()&1)?1:-1;
return t+flg*0.001*(rand()%100+1);
}
void work(){
llf X,Y,T=10000;
for(int i=1;i<=n;i++){X+=x[i];Y+=y[i];}
X/=(llf)n;Y/=(llf)n;
while(T>0.1){
T*=0.9;
llf TX=move(X),TY=move(Y);
if(cal(TX,TY)<cal(X,Y)||rand()%10000<T){X=TX;Y=TY;}
}
printf("%.3lf %.3lf\n",X,Y);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d%d",&x[i],&y[i],&g[i]);
work();
return 0;
}