zoukankan      html  css  js  c++  java
  • [模拟退火]BZOJ 3680 吊打XXX

    Description

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

    Input

    输入第一行为一个正整数n(1<=n<=10000),表示gty的数目。
    接下来n行,每行三个整数xi,yi,wi,表示第i个gty的横坐标,纵坐标和重力。
    对于20%的数据,gty排列成一条直线。
    对于50%的数据,1<=n<=1000。
    对于100%的数据,1<=n<=10000,-100000<=xi,yi<=100000

    Output

    输出1行两个浮点数(保留到小数点后3位),表示最终x的横、纵坐标。

    Sample Input

    3
    0 0 1
    0 2 1
    1 1 1

    Sample Output

    0.577 1.000
    分析
    这题luogu居然没有SPJ就跑去BZOJ做咯
    像这种优(sha)秀(bi)的题目,又是小数又是SPJ的,我觉得模拟退火这种神(sha)奇(diao)的东西能够胜任这个任务
    模拟退火是什么应该不用解释的,不过讲一下退火算法转移需要满足的条件:
    Pi→j(状态)需要以下两个要求满足其一即可:
    1、j本身比i就优(W(j)<W(i)什么的)
    2、退火算法神奇的地方:e(W(i)-W(j))/Temparetrue(仅当W(j)≥W(i)即不是更优解)
    第二条要求可能有点晕,不过这就是模拟退火的精髓:当下一解不优时,以这样一个低温函数的概率接受这个解继续求解,这样就有一定的概率跳出局部最优解,得到全局最优解。
    对于退火时的初始温度要仔细把控,过小会难以跳出局部最优解,过大时间承受不住
    还可以在算法结束后用残余的低温进行随机微调,或许可以得到更优一点的解
    #include <iostream> 
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    #define rand (double)rand()/RAND_MAX
    const double eps=1e-4;
    const double k=98*1e-2;
    const int N=10001;
    struct Point {
        double x,y,G;
    }a[N],goal;
    int n;
    double temp=1e6,mn=1e18;
    
    double Update(Point p) {
        double ret=0;
        for (int i=0;i<n;i++) ret+=sqrt(pow(a[i].x-p.x,2)+pow(a[i].y-p.y,2))*a[i].G;
        if (ret<mn) mn=ret,goal=p;
        return ret;
    }
    
    void An() {
        Point now=goal;
        while (temp>eps) {
            Point nw;
            nw.x=now.x+temp*(rand*2-1);
            nw.y=now.y+temp*(rand*2-1);
            double dE=Update(now)-Update(nw);
            if (dE>0||rand<=exp(dE/temp)) now=nw;
            temp*=k;
        }
        for (int i=1;i<=1000;i++) {
            now.x=goal.x+temp*(rand*2-1);
            now.y=goal.y+temp*(rand*2-1);
            Update(now);
        }
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=0;i<n;i++) {
            scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].G);
            goal.x+=a[i].x;goal.y+=a[i].y;
        }
        goal.x/=n;
        goal.y/=n;
        An();
        printf("%.3lf %.3lf",goal.x,goal.y);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    iOS UITextField 设置内边距
    营造积极的OKR环境
    管理者的五项基本活动
    如何在团队中让OKR深入人心
    项目管理文化:营造积极氛围的里程碑
    OKR文化:用SMART原则量化目标
    成功落地OKR的要诀
    培养一支有 OKR 思想的管理团队
    如何成为一个成功的会议领导者
    项目管理文化:开展有效的总结会议
  • 原文地址:https://www.cnblogs.com/mastervan/p/9439681.html
Copyright © 2011-2022 走看看