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 }

模拟退火 乱搞

posted on 2016-03-21 23:15  xiyuedong  阅读(140)  评论(0编辑  收藏  举报