zoukankan      html  css  js  c++  java
  • 浅谈模拟退火

    模拟退火,很有力的一个偏分武器。

    对于一类搜索,或者是有明确答案空间的题目,且不会写正解,爆搜过不去,剪枝减不了的时候,我们可以考虑用模拟退火偏分。

    模拟退火模拟的是一个物理过程,即一个物体由高温逐步降温的过程。也可以理解为,在我们寻找答案的过程中,答案所存在的范围越来越小,以此类比降温。

    也就是说,我们先开辟一个温度,或者叫搜索空间,在这个空间中,我们随机一个答案,判断这个答案和当前已知答案的优劣。

    若优于当前解,显然我们必然要更新的。如果比当前解劣呢?

    注意到,我们随机的答案是和上一个答案有关联的,有时候我们随机的将会是一个与原答案的变化幅度。也就是说,一个答案,虽然它劣,但是它的周围是可能有更优解的。

    有一个选择的准则:如果当前解优则更新;否则:

    定义(delta) ( ext{t'})为当前答案与新答案的变化幅度。则,我们以(exp(frac{-delta t'}{T}))的概率来接受这个答案。(T)表示当前的“温度”。

    我不会证这东西qwq

    然而有很多题没有这个准则,只更新更优解也可以过

    于是,我们得到一个基本算法模型:

    首先,确定温度(T).

    然后,确定降温系数。

    使得(T)在不断降温的情况下,根据当前解随机出下一个解。

    判断下一个解的优劣。并选择是否接受。

    降温。

    这个算法完成了。

    值得注意的是,如果考试要用,一定要暴力多对拍几次,今天我做题对拍了半天没有问题,然而过了一会还是出现了差别。

    如果代码过不了,注意调整初始温度和降温参数。程序的效率与它们是紧密相关的。精度不够的话可以试试( ext{long double.})

    面对不会的题也可以得分,何乐而不为呢?

    下面放一个(P1337)平衡点的代码。

    题目大意就是使得距离乘以重量的和最小,这样才平衡。

    我们退火找一个点,判断它与当前答案的差。这里的差别指的是我们求的(sum dist*wight)的差别。注意不同题目比较的标准不同,计算函数也不同。

    这份代码我没有选择概率放弃解的写法,但依旧跑的挺快。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long double db;
    const db h=0.96;
    int n;
    struct point{
        int x,y,w;
    }p[5000];
    db ansx,ansy,answ;
    inline db calc(db x,db y){
        db sum=0;
        for(int i=1;i<=n;++i){
            db dx=x-p[i].x;
            db dy=y-p[i].y;
            sum+=(sqrt(dx*dx+dy*dy))*p[i].w;
        }
        return sum;
    }
    inline void solve(){
        db T=3000;
        db x=ansx,y=ansy;
        answ=min(answ,calc(x,y));
        while(T>1e-14){
            db qx=ansx+T*(rand()*2-RAND_MAX),qy=ansy+T*(rand()*2-RAND_MAX);
            db Ew=calc(qx,qy);
            if(Ew<answ){
                answ=Ew;
                ansx=qx;
                ansy=qy;
            }
            T*=h;
        }
    }
    void work(){solve();}
    int main(){
        srand(time(0));
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w);
        answ=9999999999;work();
        printf("%.3Lf %.3Lf
    ",ansx,ansy);
        return 0;
    }
    
  • 相关阅读:
    五层原理体系结构的简单分析
    Simple Factory 简单工厂模式(静态工厂)
    css一个图片包含多个图片|网站侧栏导航
    百度地图、高德地图的数据从哪里得到的?
    浏览器开发
    开发一款浏览器内核需要学习哪些方面的知识?
    使用PowerDesigner进行数据库建模入门
    How to create a search engine
    合并两个有序数组
    STL中的algorithm
  • 原文地址:https://www.cnblogs.com/h-lka/p/12521021.html
Copyright © 2011-2022 走看看