人参中第一次膜你退货
洛谷调了调过了……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); }
忘开longlong,忘用逆元,忘删调试信息,瞬间爆炸