[bzoj2428] [HAOI2006]均分数据
模拟退火。。
随机每个数是属于哪一组的就可以了。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }