1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<ctime> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #define M 100 9 using namespace std; 10 int n,m,a[M],pos[M]; 11 double rev,sum[M],ans,mn=1e30,pre; 12 void solve() 13 { 14 memset(sum,0,sizeof(sum)); 15 ans=0; 16 for(int i=1;i<=n;i++) 17 pos[i]=rand()%m+1; 18 for(int i=1;i<=n;i++) 19 sum[pos[i]]+=a[i]; 20 for(int i=1;i<=m;i++) 21 ans+=(sum[i]-rev)*(sum[i]-rev); 22 double T=10000; 23 for(;T>0.1;) 24 { 25 int t1=rand()%n+1,x=pos[t1],y=rand()%m+1; 26 if(x==y) 27 continue; 28 T*=0.9; 29 pre=ans; 30 ans-=(sum[x]-rev)*(sum[x]-rev); 31 ans-=(sum[y]-rev)*(sum[y]-rev); 32 sum[x]-=a[t1]; 33 sum[y]+=a[t1]; 34 ans+=(sum[x]-rev)*(sum[x]-rev); 35 ans+=(sum[y]-rev)*(sum[y]-rev); 36 if(ans>pre) 37 { 38 ans=pre; 39 sum[x]+=a[t1]; 40 sum[y]-=a[t1]; 41 } 42 else 43 pos[t1]=y; 44 } 45 if(ans<mn) 46 mn=ans; 47 return; 48 } 49 int main() 50 { 51 scanf("%d%d",&n,&m); 52 for(int i=1;i<=n;i++) 53 { 54 scanf("%d",&a[i]); 55 rev+=a[i]; 56 swap(a[i],a[rand()%i+1]); 57 } 58 rev/=m; 59 for(int i=1;i<=10000;i++)solve(); 60 printf("%.2lf",sqrt(mn/m)); 61 return 0; 62 }
模拟退火 乱搞