码迷,mamicode.com
首页 > Web开发 > 详细

洛谷P1337 【[JSOI2004]平衡点 / 吊打XXX】(模拟退火)

时间:2018-04-21 12:12:05      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:star   for   mes   div   tar   ++   应该   方便   srand   

洛谷题目传送门

很可惜,充满Mo力的Mo拟退火并不是正解。不过这是一道最适合开始入手Mo拟退火的好题。

对模拟退火还不是很清楚的可以看一下

这道题还真和能量有点关系。达到平衡稳态的时候,物体的总能量应该是最小的。而总的能量来源于每个物体的重力势能之和。要想让某个物体势能减小,那就让拉着它的绳子在桌面下方的长度尽可能的长,也就是桌面上的要尽可能短。由此看来,某个物体的势能与桌面上的绳子的长度、物体重量都成正比。

于是,为了找到平衡点,我们要找一个点使得\(\sum_{i=1}^n d_i*w_i\)最小(\(d_i\)\(i\)点到该点的距离)。

函数已经求出来了,接下来就是正常的模拟退火过程。注意一些细节就好了。

首先,初始解可以设成\(({\sum_{i=1}^n x_i\over n},{\sum_{i=1}^n y_i\over n})\),可以更接近正解

解变动值最好随机两个值,\(\Delta x\)\(\Delta y\)。随机变动距离和角度可能常数有点大。

然后就是调参数的问题了。蒟蒻太懒,于是就抄了YL据老的,此题参数普遍设大一点是合理的。

最后是写法问题。蒟蒻又学习了一招,知道有一个常数叫RAND_MAX,用于生成\([0,1)\)的随机值还是很方便的,在不同机子下可移植性也很强。(难怪Windows上rand出来的都是短整形数)

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstdlib>
#define RG register
#define R RG double
#define RD T*((rand()<<1)-RAND_MAX)//生成一个-T到T的随机变动距离
const int N=1009;
const double D=0.99,EPS=1e-15;
int n;
double x[N],y[N],w[N];
inline double calc(R x0,R y0){//函数求值
    R res=0,dx,dy;
    for(RG int i=1;i<=n;++i){
        dx=x[i]-x0;dy=y[i]-y0;
        res+=sqrt(dx*dx+dy*dy)*w[i];
    }
    return res;
}
int main(){
    R T,avx=0,avy=0,start,x0,y0,x1,y1,res,ans,best,bx,by;
    RG int i,times=10;
    scanf("%d",&n);
    for(i=1;i<=n;++i){
        scanf("%lf%lf%lf",&x[i],&y[i],&w[i]);
        avx+=x[i];avy+=y[i];
    }//初始横纵坐标均选择平均值
    best=start=calc(avx/=n,avy/=n);bx=avx;by=avy;
    srand(time(NULL)*clock());
    while(times--){
        ans=start;x0=avx;y0=avy;
        for(T=1000000;T>EPS;T*=D){
            x1=x0+RD;y1=y0+RD;
            res=calc(x1,y1);
            if(best>res)
                best=res,bx=x0,by=y0;//更新答案
            if(ans>res||exp((res-ans)/T)*RAND_MAX<rand())
                ans=res,x0=x1,y0=y1;//接受新解
        }
    }
    printf("%.3lf %.3lf\n",bx,by);
    return 0;
}

洛谷P1337 【[JSOI2004]平衡点 / 吊打XXX】(模拟退火)

标签:star   for   mes   div   tar   ++   应该   方便   srand   

原文地址:https://www.cnblogs.com/flashhu/p/8900466.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!