bzoj2428: [HAOI2006]均分数据

2428: [HAOI2006]均分数据

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1671  Solved: 506
[Submit][Status][Discuss]

Description

已知N个正整数:A1、A2、……、An 。今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小。均方差公式如下:

,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值和。

 

 

Input

第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数)
第二行有N个整数,表示A1、A2、……、An。整数的范围是1--50。
(同一行的整数间用空格分开)

Output

这一行只包含一个数,表示最小均方差的值(保留小数点后两位数字)。

 

 

 

 

Sample Input

6 3
1 2 3 4 5 6

Sample Output

0.00

HINT

 

对于全部的数据,保证有K<=N <= 20,2<=K<=6

 
 
退火+数据挺弱的...代码里有注释
 1 #include<bits/stdc++.h>
 2 #define rep(i,l,r) for(int i=l;i<=r;++i)
 3 using namespace std;
 4 const int N=10233;
 5 typedef double d;
 6 d ans=1e30,ave;
 7 int n,m,a[N],sum[N],bel[N];
 8 inline void run(){
 9     memset(sum,0,sizeof sum);
10     rep(i,1,n) bel[i]=rand()%m+1,sum[bel[i]]+=a[i];
11     d sm=0,T=1000;
12     rep(i,1,m) sm+=(sum[i]-ave) * (sum[i]-ave);
13     while(T>0.0001) { //退火温度 
14         T*=0.95;
15         int t=rand()%n+1,x=bel[t],y;
16 //        if(T>500) y=min_element(sum+1,sum+1+m)-sum; //温度太高时波动大 取当前元素之和最小的一组  奇怪的东西不明为何 
17         y=rand()%m+1; //低温度开rand 
18         if(x==y) continue;
19         d tmp=sm;
20         sm-=(sum[x]-ave)*(sum[x]-ave);
21         sm-=(sum[y]-ave)*(sum[y]-ave);
22         sum[x]-=a[t],sum[y]+=a[t];
23         sm+=(sum[x]-ave)*(sum[x]-ave);
24         sm+=(sum[y]-ave)*(sum[y]-ave);
25         if(sm<=tmp) bel[t]=y; //爬山 
26         else if((rand()%10000)>T){ //不动 
27             sum[x]+=a[t]; sum[y]-=a[t];
28             sm=tmp;
29         }else bel[t]=y; //
30         ans=min(ans,sm);
31     }
32 }
33 int main(){
34     srand(19990720);
35     cin>>n>>m;
36     rep(i,1,n) cin>>a[i],ave+=a[i]; ave/=(d)m;
37     rep(i,1,5000) run();
38     printf("%.2lf\n",sqrt(ans/m));
39 }
View Code

 

posted @ 2016-09-20 13:31  Bloodline  阅读(271)  评论(0编辑  收藏  举报