退火 wa80pts求调 悬赏关注 #3 #8

P4035 [JSOI2008] 球形空间产生器

``` #include<bits/stdc++.h> using namespace std; const int N=15; int n,step=2e4; double resw; double q[N],d[N]; double dot[N][N],ans[N],res[N]; double ner(double l,double r) { l=max(l,-2e4);r=min(r,2e4); return (double)rand()/RAND_MAX*(r-l)+l; } double calc(double a[]) //计算方差 { double avg=0,sum=0; memset(d,0,sizeof d); for(int i=1;i<=n+1;i++) { for(int j=1;j<=n;j++) d[i]+=(a[j]-dot[i][j])*(a[j]-dot[i][j]); avg+=d[i]; } avg/=(double)(n+1); for(int i=1;i<=n+1;i++) sum+=(d[i]-avg)*(d[i]-avg); return sum; } void sa() { memcpy(res,ans,sizeof res); for(double t=1e6;t>=1e-15;t*=0.99764) { for(int i=1;i<=n;i++) q[i]=ner(res[i]-step*t,res[i]+step*t); double dw=calc(q); double ned=dw-resw; if(ned<0.0) //更优直接转移 { memcpy(ans,q,sizeof ans); memcpy(res,q,sizeof res); resw=dw; } else if(exp(-ned/t)>ner(0,1)) memcpy(res,q,sizeof res); //更劣概率转移 } } int main() { scanf("%d",&n); for(int i=1;i<=n+1;i++) for(int j=1;j<=n;j++) scanf("%lf",&dot[i][j]),ans[j]+=dot[i][j]; for(int i=1;i<=n;i++) ans[i]/=(double)(n+1); resw=calc(ans); while((double)clock()/CLOCKS_PER_SEC<0.96) sa(); // sa(),sa(),sa(),sa(),sa(); for(int i=1;i<=n;i++) printf("%.3lf ",ans[i]); return 0; } ``` @[xyzfrozen](/user/749714) ,调好了,你的代码我就收下了
by Zikl @ 2023-03-16 21:29:17


@[xyzfrozen](/user/749714) 1e-15更精确一点
by Zikl @ 2023-03-16 21:31:07


@[Zikl](/user/300166) !谢谢大佬
by xyzfrozen @ 2023-03-16 21:55:23


@[xyzfrozen](/user/749714) 为什么你的退火没有随机种子?
by Aisaka_Taiga @ 2023-08-21 14:44:39


@[Aisaka_Taiga](/user/526519) 啊?只能说退火太强了
by xyzfrozen @ 2023-08-21 16:38:26


@[xyzfrozen](/user/749714) 设上种子试试,那样起码不用调参调到小数点后好几位。
by Aisaka_Taiga @ 2023-08-21 16:40:20


@[Aisaka_Taiga](/user/526519) 没用 [record](https://www.luogu.com.cn/record/122094487)
by xyzfrozen @ 2023-08-21 16:58:56


@[xyzfrozen](/user/749714) 你看我提交的。 https://www.luogu.com.cn/record/122070592
by Aisaka_Taiga @ 2023-08-21 17:09:00


@[Aisaka_Taiga](/user/526519) 估计没卡这个,精度够了就行(悲)
by xyzfrozen @ 2023-08-21 17:11:12


|