多校第十场HRBEU &&hdu 3932 Groundhog Build Home(模拟退火算法)

WA了一下午,根据题目性质感觉不应该出现极值点,但是跑了遍数据,发现还是有因为误跑到极值点挂掉的数据

模拟退火算法(Simulated Annealing,SA)最早由Kirkpatrick等应用于组合优化领域,它是基于Mente-Carlo迭代求解策略的一种随机寻优算法,其出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。模拟退火算法是一种通用的优化算法,理论上算法具有概率的全局优化性能,目前已在工程中得到了广泛应用,诸如VLSI、生产调度、控制工程、机器学习、神经网络、信号处理等领域。

模拟退火算法是通过赋予搜索过程一种时变且最终趋于零的概率突跳性,从而可有效避免陷入局部极小并最终趋于全局最优的串行结构的优化算法。

PDF教程 http://www.doc88.com/p-17185317870.html 

题意是在给定的范围内找个满足到其他各点最大距离最小的点,该条件不满足三角不等式,比如0 0 100 100 在0 100处向x,y2个方向都增大,此时为局部最优解,但不是最后的解;

模拟退火时的3个变量的火候都需要自己掌握,徘徊在WA与TLE之间的AC。。。

 

#include <cstdio>
#include <cmath>
#include <time.h>
#include <cstdlib>
using namespace std;

const double pi=acos(-1.0);
const int maxn=1005;
double x[maxn], y[maxn];
int n;

double dis2 (double x1,double y1 ,double x2,double y2)//距离平方 
{
       double tmp1=x1-x2,tmp2=y1-y2;
       tmp1*=tmp1;
       tmp2*=tmp2;
       return tmp1+tmp2;
}

double test(double xx, double yy) 
{
       double max = 0,tmp;
       for (int i=0;i<n;i++)
           if(max<(tmp=dis2(xx,yy,x[i],y[i])))max=tmp;
       return max;
}


int main()
{
    double xx,yy;
    double delta,theta;
    double X,Y;
    double retx,rety,ans;
    //freopen ("in.in","r",stdin);
    //freopen ("out.txt","w",stdout);
    while (~scanf("%lf%lf%d",&X,&Y,&n))
    {
        for (int i=0 ; i<n ; i++)
            scanf("%lf%lf",x+i,y+i);
        double ans=1000000000.0;
        for (int i=0 ; i<10 ; ++i)
        {
            xx=((double)(rand()%1001)/1000.0)*X;
            yy=((double)(rand()%1001)/1000.0)*Y;
            //printf("%lf,%lf\n",xx,yy);
            double dis=test(xx,yy);
            for (delta=X ; delta>0.001 ; delta*=0.9) 
            {
                for (theta=0 ; theta<=2*pi ; theta+=(pi/25.0))
                {
                    double tx=xx+delta*cos(theta);
                    double ty=yy+delta*sin(theta);
                    double tdis=test(tx,ty);
                    if(tdis<dis)
                    {
                        xx=tx;
                        yy=ty;
                        dis=tdis;
                    }
                }
            }
            //printf("%lf\n",dis);
            if(dis<ans)
            {
                retx=xx;
                rety=yy;
                ans=dis;
            }
        }
        printf("(%.1lf,%.1lf).\n%.1lf\n",retx,rety,sqrt(ans));
    }
    return 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值