人参中第一次膜你退货

洛谷调了调过了……bzoj调了一晚上快把评测卡了还是没过……

不过还是感觉这个算法肥肠神奇,是一个可以带给人们欢乐的算法。

算法思想极为简单,先随便得出一个不优解,然后每次在这个不优解的周围随机跳动,随机跳动幅度随时间推移减小,如果到了更优的解则更新;如果解不是更优的则有T的概率更新,T随时间推移减小。

算法主要难点在于参数的设置,包括初始幅度,幅度减小的速率,还有T。这玩意过于玄学我缺乏人生经验希望有大佬指点一二。

睿智的模板

#include<bits/stdc++.h>
using namespace std;
struct thing
{
    double x,y,w;
}a[1001];
int n;
double ansx,ansy,t,ans;
#define T 0.998
double calc(double x,double y)
{
    double res=0;
    for(int i=1;i<=n;i++)
    {
        res+=sqrt((a[i].x-x)*(a[i].x-x)+(a[i].y-y)*(a[i].y-y))*a[i].w;
    }
    return res;
}
void fire()
{
    double xx=ansx,yy=ansy;
    t=1270;
    for(;t>=1e-14;t*=T)
    {
        double x=xx-(rand()*2-RAND_MAX)*t,y=yy-(rand()*2-RAND_MAX)*t;
        double tmp=calc(x,y),d=tmp-ans;
        if(d<0)
        {
            ans=tmp;
            ansx=x,ansy=y,xx=x,yy=y;
        }
        else if( exp(-d/t)*RAND_MAX>rand())
            xx=x,yy=y;
    }
}
int main()
{
    srand(20011115);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].w);
        ansx+=a[i].x,ansy+=a[i].y;
    }
    ansx/=(double)n,ansy/=(double)n;
    ans=calc(ansx,ansy);
    for(int i=1;i<=8;i++)
    fire();
    printf("%.3lf %.3lf",ansx,ansy);
}
View Code

 

posted @ 2018-10-12 09:15  _hcy_a  阅读(180)  评论(2编辑  收藏  举报