• LUOGU P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)


    传送门

    解题思路

    学习了一下玄学算法--模拟退火,首先要求平衡处,也就是求势能最小的地方,就是求这个点到所有点的距离*重量最小。剩下的几乎是模拟退火的板子了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 10005;
    const double delta = 0.98;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,x[MAXN],y[MAXN],w[MAXN];
    double ans=1e18,t,ansx,ansy,sx,sy;
    
    double calc(double X,double Y){
        double ret=0,cx,cy;
        for(register int i=1;i<=n;i++){
            cx=X-x[i];cy=Y-y[i];
            ret+=sqrt(cx*cx+cy*cy)*w[i];
        }
        return ret;
    }
    
    void SA(){
        double xx=ansx,yy=ansy,X,Y,now,D;
        t=2000;
        while(t>1e-14){
            X=xx+((rand()<<1)-RAND_MAX)*t;
            Y=yy+((rand()<<1)-RAND_MAX)*t;
            now=calc(X,Y);D=now-ans;
            if(D<0){
                xx=X,yy=Y;ans=now;
                ansx=xx,ansy=yy;
            }
            else if(exp(-D/t)*RAND_MAX>rand()) xx=X,yy=Y;
            t*=delta;
        }
    }
    
    void Solve(){
        ansx=(double)sx/n,ansy=(double)sy/n;
        SA();SA();SA();
    }
    
    int main(){
        srand(19260817);srand(rand());srand(rand());
        n=rd();
        for(int i=1;i<=n;i++) x[i]=rd(),y[i]=rd(),w[i]=rd(),sx+=x[i],sy+=y[i];
        Solve();
        printf("%.3lf %.3lf",ansx,ansy);
        return 0;
    }
    View Code
  • 相关阅读:
    MySQL存储过程
    [转载]JDBC应该始终以PreparedStatement代替Statement
    Restlet入门例子 RESTful web framwork for java
    Cglib的使用方法(3)Mixin
    HDOJ_1220
    精华:OracleHelper类
    web.config详解
    ADO.NET结构
    字典树
    WCF、Net remoting、Web service概念及区别
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9724019.html
Copyright © 2020-2023  润新知