模拟退火(SA)模板

退役很久了,今天看一篇paper用SA算法代替随机梯度优化神经网络,故学习一波SA算法。

因为网上的资料很多,所以这里就不多说啦。

详情可以看https://www.cnblogs.com/rvalue/p/8678318.html

高中生太强啦

这里放一个模板~

题目链接:https://www.luogu.org/problemnew/show/P1337

P1337 [JSOI2004]平衡点 / 吊打XXX

题目描述

如图:有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。

问绳结X最终平衡于何处。

注意:桌面上的洞都比绳结X小得多,所以即使某个重物特别重,绳结X也不可能穿过桌面上的洞掉下来,最多是卡在某个洞口处。

输入输出格式

输入格式:

 

文件的第一行为一个正整数n(1≤n≤1000),表示重物和洞的数目。接下来的n行,每行是3个整数:Xi.Yi.Wi,分别表示第i个洞的坐标以及第 i个重物的重量。(-10000≤x,y≤10000, 0

 

输出格式:

 

你的程序必须输出两个浮点数(保留小数点后三位),分别表示处于最终平衡状态时绳结X的横坐标和纵坐标。两个数以一个空格隔开。

 

输入输出样例

输入样例#1: 复制

3
0 0 1
0 2 1
1 1 1

输出样例#1: 复制

0.577 1.000

说明

[JSOI]

 

代码:

#include 

using namespace std;
const int N = 1e4+10;

struct Point
{
    double x,y;
    Point(double x=0,double y=0)
    {
        this->x=x;
        this->y=y;
    }
}p[N];
int n;
double g[N];
Point ans;
double minAns=DBL_MAX;
double Rand()
{
     return double(rand())/double(RAND_MAX);
}
double Sqr(double a)
{
    return a*a;
}
double Eulc(Point A,Point B)
{
    return sqrt(Sqr(A.x-B.x)+Sqr(A.y-B.y));
}

double Calc(Point A)
{
    double ans=0;
    for(int i=0;iendT)
    {
        Point next = Point(now.x+tmp*(2*Rand()-1),now.y+tmp*(2*Rand()-1));
        double ans = Calc(next);
        if(Accept(ans-nowAns,tmp))
        {
            nowAns=ans;
            now=next;
        }
        tmp*=dec;
    }
    for(int i=0;i<10000;i++)
    {
        Point rnc = Point(ans.x+tmp*(2*Rand()-1),ans.y+tmp*(2*Rand()-1));
        Calc(rnc);
    }
    return now;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        Point init;
        init.x=init.y=0.0;
        for(int i=0;i

能不能AC全看脸,启发式算法为了逼近全局最优解,其中包含有随机值。

当然实际使用中,我们往往并不需要最优解,而只要一个逼近最优解的值就行了。

你可能感兴趣的:(模拟退火(SA)模板)