bzoj3680: 吊打XXX

题目链接

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; 
}
posted @ 2018-05-06 14:42  zzzzx  阅读(157)  评论(0编辑  收藏  举报