[bzoj2428] [HAOI2006]均分数据

  模拟退火。。

  随机每个数是属于哪一组的就可以了。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #define d double
 7 using namespace std;
 8 int sm[7],bel[21],a[21];
 9 int i,j,k,n,m;
10 d avg,sqr[1023],mn;
11 int ra;char rx;
12 inline int read(){
13     rx=getchar(),ra=0;
14     while(rx<'0'||rx>'9')rx=getchar();
15     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
16 }
17 inline void run(){
18     d T=10023;register int i;d ans=0,tmp;
19     int j,x,y;
20     for(i=0;i<m;i++)sm[i]=0;
21     for(i=0;i<n;i++)sm[bel[i]=rand()%m]+=a[i];
22     for(i=0;i<m;i++)ans+=sqr[sm[i]];
23 //    for(i=0;i<m;i++)printf("  %d",sm[i]);puts("");printf("   %.2lf\n",ans);
24     while(T>0.1){
25         T*=0.9;
26         x=bel[j=rand()%n];
27         if(T<500)y=rand()%m;else
28             for(i=1,y=0;i<m;i++)if(sm[i]<sm[y])y=i;
29         
30         if(x==y)continue;
31     //    for(i=0;i<m;i++)printf("  %d",sm[i]);puts("");
32         tmp=ans-sqr[sm[y]]-sqr[sm[x]]+sqr[sm[y]+a[j]]+sqr[sm[x]-a[j]];
33     //    printf("move:%d  %d-->%d    %.2lf\n",j,bel[j],k,tmp);
34         if(tmp<=ans||(rand()%10000<T))
35             sm[x]-=a[j],bel[j]=y,sm[y]+=a[j],ans=tmp;
36     }
37     if(ans<mn)mn=ans;
38 }
39 int main(){
40     n=read(),m=read();
41     for(i=0;i<n;i++)a[i]=read(),avg+=a[i];
42     avg/=m;
43     for(i=0;i<=1000;i++)sqr[i]=(i-avg)*(i-avg);//,printf("%d %.2lf\n",i,sqr[i]);
44     mn=1e23;
45     for(i=10023;i&&mn>1e-7;i--)run();
46     printf("%.2lf\n",sqrt(mn/m));
47     return 0;
48 }
View Code

 

posted @ 2016-03-21 13:04  czllgzmzl  阅读(242)  评论(0编辑  收藏  举报