zoukankan      html  css  js  c++  java
  • [HAOI2006]均分数据

    题目:洛谷P2503。

    题目大意:
    有(a_1,a_2,dots,a_n),现在要将它们分成(m)组。
    $$sigma =frac{sum_{i=1}^m (x_i-ar{x})^2}{m}$$ 其中(ar{x}=frac{sum_{i=1}^n a_i}{n}),(x_i)为第(i)组的数值和。
    问(sigma)最小是多少。
    解题思路:
    模拟退火。
    每次random_shuffle出一个排列,然后dp出该排列最小可能的答案,然后模拟退火。
    调参真是麻烦,交了几十发只过了一发。

    C++ Code:

    #include<bits/stdc++.h>
    #define eps 1e-15
    #define delta 0.9901
    using namespace std;
    int n,m,a[22],s[22];
    double ans=233333333.19260817,f[22][22],br=0;
    inline double min(const double a,const double b){return a<b?a:b;}
    inline double sqr(const double x){return x*x;}
    double calc(){
        memset(f,0x7f,sizeof f);
        f[0][0]=0;
        s[0]=0;
        for(int i=1;i<=n;++i)s[i]=s[i-1]+a[i];
        for(int i=1;i<=n;++i)
        for(int j=1;j<i&&j<=m;++j)
        for(int k=0;k<i;++k)
        f[i][j]=min(f[i][j],f[k][j-1]+sqr(s[i]-s[k]-br));
        return f[n][m];
    }
    int main(){
        ios::sync_with_stdio(0),cin.tie(0);
        cin>>n>>m;
        for(int i=1;i<=n;++i)cin>>a[i];
        for(int i=1;i<=n;++i)br+=a[i];
        br/=m;
        srand(time(0));
        for(int T=1;T<=15;++T){
            double now=ans;
            for(double nT=10000;nT>eps;nT*=delta){
                random_shuffle(a+1,a+n+1);
                double nw=calc();
                if(nw<ans)ans=nw;
                if(nw<now||exp((now-nw)/nT)*RAND_MAX<rand())
                now=nw;
            }
        }
        printf("%.2f
    ",sqrt(ans/m));
        return 0;
    }
    
  • 相关阅读:
    装饰器
    函数的初识
    python的文件操作
    深浅copy
    set集合,是一个无序且不重复的元素集合
    基础数据类型 :字典
    列表的增删改查
    易错点 默认参数陷阱
    js中Array对象常用方法
    printf用法demo
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9179455.html
Copyright © 2011-2022 走看看