洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX

洛谷 P1337 [JSOI2004]平衡点 / 吊打XXX


点击进入FakeHu的模拟退火博客

神仙模拟退火。。。去看fakehu的博客吧。。。懒得写了。。。

因为精度问题要在求得的最优解附近(大约0.01以内随机找解更新

成功创造此题唯一一个9000ms。。。。链接(反正你也点不进去=。=

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
long double x[10010],y[10010],w[10010];
il long double dist(const int&a,const int&b){return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));}
int main(){
    int n=gi();
    for(int i=1;i<=n;++i)x[i]=gi(),y[i]=gi(),w[i]=gi();
    long double best,ax,ay,nx,ny,now,tem,px,py,res;
    best=0,ax=x[1],ay=y[1];for(int i=1;i<=n;++i)best+=dist(1,i)*w[i];
    int tot=1;
    srand(time(NULL));
#define RAND (2.00*rand()/RAND_MAX-1)
    while(tot--){
        nx=ax,ny=ay;now=best;tem=100000;
        while(tem>1e-14){
            px=x[0]=nx+RAND*tem;
            py=y[0]=ny+RAND*tem;
            res=0;
            for(int i=1;i<=n;++i)res+=dist(i,0)*w[i];
            if(res<best)best=res,ax=px,ay=py;
            if(res<now||rand()*1.0/RAND_MAX<exp((best-res)/tem))now=res,nx=px,ny=py;
            tem*=0.97;
        }
    }
    while(clock()*1.00/CLOCKS_PER_SEC<0.999){
        px=x[0]=ax+RAND*0.1;
        py=y[0]=ay+RAND*0.1;
        res=0;
        for(int i=1;i<=n;++i)res+=dist(i,0)*w[i];
        if(res<best)best=res,ax=px,ay=py;
    }
    printf("%.3Lf %.3Lf
",ax,ay);
    return 0;
}
原文地址:https://www.cnblogs.com/xzz_233/p/9740071.html