退火 wa80pts求调 悬赏关注 #3 #8
查看原帖
退火 wa80pts求调 悬赏关注 #3 #8
749714
xyzfrozen楼主2023/1/30 13:29

rt求调

#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-8;t*=0.99864)
    {
        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;
}
2023/1/30 13:29
加载中...