[BZOJ 3680]吊打XXX(模拟退火)

Description

gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty。gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了。蒟蒻们将n个gty吊在n根绳子上,每根绳子穿过天台的一个洞。这n根绳子有一个公共的绳结x。吊好gty后蒟蒻们发现由于每个gty重力不同,绳结x在移动。蒟蒻wangxz脑洞大开的决定计算出x最后停留处的坐标,由于他太弱了决定向你求助。不计摩擦,不计能量损失,由于gty足够矮所以不会掉到地上。

Solution

题面丧病…似乎是一道模拟退火的板子题,求的那个东西叫做广义费马点

从昨天晚上WA到今天,各种调参数

呜呜呜RP太差了…AC率又不知道掉到哪里去了…再也不玩什么随机化算法了…

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#define MAXN 10005
using namespace std;
int n;
int x[MAXN],y[MAXN],w[MAXN];
double ansmin_x,ansmin_y,t;
double ansx=0,ansy=0;
inline double read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
inline double Random(){return (double)(rand()%10000)/10000.0;}
inline double dis(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double judge(double xx,double yy)
{
    double res=0;
    for(int i=1;i<=n;i++)
    res+=dis(xx,yy,x[i],y[i])*w[i];
    if(res<t)t=res,ansmin_x=xx,ansmin_y=yy;
    return res;
}
int main()
{
    srand(299792458);
    n=read();
    for(int i=1;i<=n;i++)
    x[i]=read(),y[i]=read(),w[i]=read(),ansx+=x[i],ansy+=y[i];
    ansx/=n,ansy/=n;
    ansmin_x=ansx,ansmin_y=ansy,t=judge(ansx,ansy);
    double T=1e6,r=0.99;
    while(T>1e-3)
    {
        double xx,yy;
        xx=ansx+T*(Random()*2-1.0);
        yy=ansy+T*(Random()*2-1.0);
        double dE=judge(ansx,ansy)-judge(xx,yy);
        if(dE>0||exp(dE/T)>Random())ansx=xx,ansy=yy;
        T*=r;
    }
    for(int i=1;i<=1000;i++)
    {
        double xx=ansmin_x+(Random()*2-1.0)*T,yy=ansmin_y+(Random()*2-1.0)*T;
        judge(xx,yy);
    }
    printf("%.3lf %.3lf
",ansmin_x,ansmin_y);
    return 0;
}
原文地址:https://www.cnblogs.com/Zars19/p/6979072.html