模拟退火大法好!
我的退火为何如此渣
而且为何我的生日只能跑0.9
可是6662333 就能跑0.8
qwq
代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<climits>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
const int N=105;
int n,m,belong[N];
double ave,a[N],sum[N];
inline double solve(){
sum[0]=1e30;
for(int i=1;i<=m;++i)sum[i]=0;
for(int i=1;i<=n;++i)belong[i]=rand()%m+1,sum[belong[i]]+=a[i];
double t=1e4,last,ans=0;
for(int i=1;i<=m;++i)ans+=(sum[i]-ave)*(sum[i]-ave);
for(;t>1e-1;t*=0.8){
last=ans;
int x=rand()%n+1,y=0;
if(t>500)y=rand()%m+1;
else for(int i=1;i<=m;++i)if(sum[i]<sum[y])y=i;
if(x==y)continue;
ans+=a[x]*(a[x]+sum[y]-sum[belong[x]])*2;
if(ans>last){
if(rand()%10000<t){
sum[belong[x]]-=a[x];
belong[x]=y;
sum[belong[x]]+=a[x];
}
else ans=last;
}
else{
sum[belong[x]]-=a[x];
belong[x]=y;
sum[belong[x]]+=a[x];
}
}
return ans;
}
int main(){
srand(6662333);
n=read();m=read();double ans=1e30;
for(int i=1;i<=n;++i)a[i]=read(),ave+=a[i];
ave/=m;
for(int i=1;i<=10000;++i)ans=min(ans,solve());
printf("%.2lf",sqrt(ans/m));
return 0;
}