P1337 [JSOI2004]平衡点 / 吊打XXX 模拟退火

链接

https://www.luogu.org/problemnew/show/P1337

思路

交了好多发,都是wrong
初始值取平均数就1A了
真的是玄学的算法

代码

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-15;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
struct node {
    double x,y,w;
}e[1007];
double n,ansx,ansy;
double dis(int a,double x_,double y_) {
    return sqrt((e[a].x-x_)*(e[a].x-x_)+(e[a].y-y_)*(e[a].y-y_));
}
double calc(double x,double y) {
    double ans=0;
    for(int i=1;i<=n;++i)
        ans+=dis(i,x,y)*e[i].w;
    return ans;
}
void mnth() {
    double T=3000;
    while(T>eps) {
        double nowx=ansx+(rand()*2-RAND_MAX)*T;
        double nowy=ansy+(rand()*2-RAND_MAX)*T;
        double delta=calc(nowx,nowy)-calc(ansx,ansy);
        // cout<<ansx<<" "<<ansy<<"\n";
        if(delta<0) {
            ansx=nowx,ansy=nowy;
        } else if(exp(-delta/T)*RAND_MAX>rand()) {
            ansx=nowx,ansy=nowy;
        }
        T*=0.996;
    }
}
int main() {
    // freopen("a.in","r",stdin);
    srand(time(NULL));
    n=read();
    for(int i=1;i<=n;++i) {
        e[i].x=read(),e[i].y=read(),e[i].w=read();
        ansx+=e[i].x;
        ansy+=e[i].y;
    }
    ansx/=n;
    ansy/=n;
    mnth();
    mnth();
    mnth();
    mnth();
    printf("%.3f %.3f\n",ansx,ansy);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dsrdsr/p/10492870.html
今日推荐