bzoj3680: 吊打XXX
题目链接
题解
物理题
问题转化为求力的重心
模拟退火即可
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 100007;
double x[maxn],y[maxn],w[maxn];
int n;double ansx,ansy,nowx,nowy,Ans = 1.0 * 1e18;
double calc(double X,double Y) {
double ret = 0;
for(int i = 1;i <= n;++ i)
ret += w[i] * sqrt((X - x[i]) * (X - x[i]) + (Y - y[i]) * (Y - y[i]));
if(ret < Ans) Ans = ret,ansx = X,ansy = Y;
return ret;
}
double Random() {return (double) rand() / RAND_MAX;}
void SA(double T) {
nowx = ansx,nowy = ansy;
double tmpx ,tmpy;
while(T > 0.001) {
tmpx = nowx + T * (Random() * 2 - 1);
tmpy = nowy + T * (Random() * 2 - 1);
double DE = calc(nowx,nowy) - calc(tmpx,tmpy);
if(DE > 0 || Random() <= exp(DE/T))
nowx = tmpx,nowy = tmpy;
T *= 0.98;
}
for(int i = 1;i <= 1000;++ i) {
tmpx = ansx + T * (Random() * 2 - 1) ;
tmpy = ansy + T * (Random() * 2 - 1) ;
calc(tmpx,tmpy);
}
}
int main() {
srand(19260817);
scanf("%d",&n);
for(int i = 1;i <= n;++ i) scanf("%lf%lf%lf",x + i,y + i,w + i),
ansx += x[i],ansy += y[i];
ansx /= n;ansy /= n;
//printf("%lf %lf\n",Ans,ansy);
SA(40000001);
printf("%.3lf %.3lf",ansx,ansy);
return 0;
}