#include<bits/stdc++.h>
#define int long long
using namespace std;
double T=3000,Down=0.998,eps=1e-10;
int g[8][25],ng[8][25],ans,ori[200];
int n,m;
double f(){
double res=0,a=0;
int y[25];
for(int i=1;i<=m;i++) y[i]=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
y[i]+=ng[i][j];
a+=y[i];
}
a=a/(m*1.0);
for(int i=1;i<=m;i++)
res+=(a-y[i])*(a-y[i]);
res=res/(m*1.0);
return sqrt(res);
}
double gf(){
double res=0,a=0;
int y[25];
for(int i=1;i<=m;i++) y[i]=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
y[i]+=g[i][j];
a+=y[i];
}
a=a/(m*1.0);
for(int i=1;i<=m;i++)
res+=(a-y[i])*(a-y[i]);
res=res/(m*1.0);
return sqrt(res);
}
int random(int x){
return rand()*rand()%x+1;
}
double F;
void SA(){
T=3000;
F=gf();
while(T>eps){
int g1=random(m),g2=random(m),x1=random(n),x2=random(n);
while(g1==g2||(ng[g1][x1]==0&&ng[g2][x1]==0)) g1=random(m),g2=random(m),x1=random(n),x2=random(n);
swap(ng[g1][x1],ng[g2][x2]);
double Fn=f();
if(Fn<F){
F=Fn;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) g[i][j]=ng[i][j];
}
else{
double chance=exp(-(Fn-F)/T);
if(rand()<RAND_MAX*chance){
F=Fn;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) g[i][j]=ng[i][j];
}
else{
swap(ng[g1][x1],ng[g2][x2]);
}
}
T*=Down;
}
}
int cnt;
signed main(){
srand(time(NULL));
cin>>n>>m;
cnt=n;
for(int i=1;i<=n;i++)
cin>>ori[i];
for(int i=2;i<=m;i++)
for(int j=1;j<=n;j++)
ori[++cnt]=0;
clock_t Begin=clock(),End;
double ans=1e18;
for(int k=1;k<=1;k++){
random_shuffle(ori+1,ori+1+n*m);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) g[i][j]=ng[i][j]=ori[(i-1)*n+j];
SA();
ans=min(ans,F);
End=clock();
if((double)(End-Begin)/CLOCKS_PER_SEC*1000.0>=950) break;
}
printf("%.2f\n",ans);
return 0;
}
求函数值就是直接O(nm)暴力求的
assert检查好像跑出来好多0.00
和题解对拍跑出来差不多甚至更优(