模拟退火又不行了,求救`(*>﹏<*)′
查看原帖
模拟退火又不行了,求救`(*>﹏<*)′
828664
Llx2022楼主2023/7/19 22:22

#include<iostream>
#include<cstring>
#include<cmath>
#include<ctime>
#include<random>
#include<stdlib.h>
using namespace std;
const int N=21;
int n,m;
double a[N];
#include<assert.h>
const double eps=1e-10;
double b[N];
double calc(){
    memset(b,0,sizeof b);
    double an=0;
    for(int i=1;i<=m;i++){
        for(int j=(i-1)*ceil(n/m)+1;j<=i*ceil(n/m);j++){
            b[i]+=a[j];
        }
    }
    double avg=0;
    for(int i=1;i<=m;i++){
        avg+=b[i];
    }
    avg/=m;
    for(int i=1;i<=m;i++){
        an+=(avg-b[i])*(avg-b[i]);
    }
    an/=m;
    an=sqrt(an);
    return an;
}
double ans=1e9;
void sa(){
    int last=0;
    for(double t=3000;t>=eps;t*=0.999){
        int xx=rand()%n+1;
        int yy=rand()%n+1;
        swap(a[xx],a[yy]);
        double res=calc();
        double dt=res-last;
        if(dt<0){
            ans=min(res,ans);
            last=res;
        }
        else if(exp(-dt/t)<(double)rand()/RAND_MAX){
            last=res;
        }
        else{
            swap(a[xx],a[yy]);
        }
    }
}
int main(){
    srand(time(0));
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    ans=calc();
    for(int i=1;i<=10;i++){
        sa();
    }
    printf("%.2lf",ans);
    return 0;
}
2023/7/19 22:22
加载中...