社区讨论

模拟退火[76,92]pts求条

P7962[NOIP2021] 方差参与者 3已保存回复 11

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
11 条
当前快照
1 份
快照标识符
@migu5zfn
此快照首次捕获于
2025/11/27 10:50
3 个月前
此快照最后确认于
2025/11/28 17:23
3 个月前
查看原帖
说点闲话,考前要写模拟提升信心,但是我不想写勾石大模拟,所以我写模拟退火awa
如题,凹了好久,这疑似是目前我能找到的最好的参数了,但是给的大样例出解率低达5%
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+10;
const double MAX_TIME=0.95;
int n,a[N],c[N],cnt,cntans;
int rnd(int l,int r)
{
    return rand()%(r-l+1)+l;
}
double check()
{
    double p=0,cc=0;
    for(int i=1;i<=n;i++)
    {
        a[i]=a[i-1]+c[i];
        p+=a[i];
    }
    p/=n;
    for(int i=1;i<=n;i++)
    {
        cc+=(a[i]-p)*(a[i]-p);
    }
    return cc/n;
}
bool cmp(int x,int y)
{
    return x>y;
}
double SA()
{
    double mn=1e18+7;
    while(true)
    {
        int _=rnd(n/3,n/3*2);
        sort(c+2,c+1+_,cmp);
        sort(c+1+_,c+1+n);
        double mk=check();
        for(double t=1e8;t>=1e-8;t*=0.9999)
        {
            int x=rnd(2,n),y=rnd(2,n);
            if(x==y)continue;
            swap(c[x],c[y]);
            double nk=check();
            if(nk<mk||(double)exp((mk-nk)/t)*RAND_MAX>rand())
            {
                mk=nk;
            }
            else
            {
                swap(c[x],c[y]);
            }
            mn=min(mn,mk);
            if((double)clock()/CLOCKS_PER_SEC>=MAX_TIME)
            {
                return mn*n*n;
            }
        }
    }
    return mn*n*n;
}
signed main()
{
    //freopen("variance4.in","r",stdin);
    srand(time(NULL));
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        c[i]=a[i]-a[i-1];
    }
    cout<<(int)(SA()+0.99)<<"\n";
    return 0;
}

回复

11 条回复,欢迎继续交流。

正在加载回复...