2428: [HAOI2006]均分数据
Time Limit: 20 Sec Memory Limit: 256 MB
题目连接
http://www.lydsy.com/JudgeOnline/problem.php?id=2428
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
题意
题解:
随机化搞搞搞!http://www.cnblogs.com/rausen/p/4324676.html
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200001 #define mod 10007 #define eps 1e-9 int Num; char CH[20]; //const int inf=0x7fffffff; //нчоч╢С const ll inf=1e60; /* inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } */ inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } //************************************************************************************** double a[maxn]; int p[maxn]; int n,m; double sum; double ave; double ans; double sqr(double a) { return a*a; } double solve() { int cnt = 1, sum = 0, i; double tmp = 0, t1, t2; for (i = 1; i <= n && cnt < m; ++i) if (sum + a[p[i]] >= ave) { t1 = sqr(sum - ave), t2 = sqr(sum + a[p[i]] - ave); if (t1 < t2) tmp += t1, sum = a[p[i]]; else tmp += t2, sum = 0; ++cnt; } else sum += a[p[i]]; while (i <= n) sum += a[p[i++]]; tmp += sqr(sum - ave); return tmp; } int main() { //freopen("test.txt","r",stdin); n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=read(); sum+=a[i]; p[i]=i; } ave=sum/m; ans=-1; int cntt=0; while(cntt<500000) { random_shuffle(p+1,p+1+n); if(ans==-1) ans=solve(); else ans=min(solve(),ans); cntt++; } printf("%.2lf\n",sqrt(ans/m)); }