• bzoj2428[HAOI2006]均分数据


    bzoj2428[HAOI2006]均分数据

    题意:

    已知N个正整数,将它们分成M组,使各组数据的数值和最平均,即各组的均方差最小,求最小均方差。

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

    题解:

    神奇的模拟退火算法!它是爬山算法的加强版。爬山算法是一种贪心算法,对于每个状态,除非随机选出一个后继状态比它好,才会跳过去。但这样有可能“一叶障目不见泰山”,产生错误的答案。但模拟退火不一样,它如果找到一个后继状态比当前状态差,也有一定概率跳过去,但这概率和跳跃次数成反比。这样即使被“一叶障目”,也有机会绕过叶子,找到泰山。

    关于爬山算法与模拟退火,有一个有趣的比喻:

      爬山算法:兔子朝着比现在高的地方跳去。它找到了不远处的最高山峰。但是这座山不一定是珠穆朗玛峰。这就是爬山算法,它不能保证局部最优值就是全局最优值。

      模拟退火:兔子喝醉了。它随机地跳了很长时间。这期间,它可能走向高处,也可能踏入平地。但是,它渐渐清醒了并朝最高方向跳去。这就是模拟退火。

    这个算法写法实际上是模拟一个物理降温过程,然而对我这种物理渣~~只能背代码框架了QAQ

    回到本题,首先给每个数据随机分到一个组,做5000次模拟退火。当温度比较高时跳跃不稳定,所以贪心一下,随机找一个数据,然后把它放进当前和最小的那个组;当温度渐低后,就随机找一个数据然后随机放组。关于退火的次数,网上题解里是10000,我试过1000会不能过,但是5000能过且比10000要快一倍,所以代码给出的是5000。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #define inc(i,j,k) for(int i=j;i<=k;i++)
     7 #define INF 0x3fffffff
     8 using namespace std;
     9 
    10 int n,m,pos[100]; double a[100],sum[100],ave,mn,T,ans,pre;
    11 void solve(){
    12      memset(sum,0,sizeof(sum)); inc(i,1,n)pos[i]=rand()%m+1,sum[pos[i]]+=a[i]; ans=0;
    13      inc(i,1,m)ans+=(sum[i]-ave)*(sum[i]-ave); T=10000;
    14      while(T>0.1){
    15          pre=ans; int x=rand()%n+1,y;
    16          if(T>500)y=min_element(sum+1,sum+1+m)-sum;else y=rand()%m+1; if(pos[x]==y)continue;
    17          ans-=(sum[pos[x]]-ave)*(sum[pos[x]]-ave); ans+=(sum[pos[x]]-a[x]-ave)*(sum[pos[x]]-a[x]-ave); 
    18         ans-=(sum[y]-ave)*(sum[y]-ave); ans+=(sum[y]+a[x]-ave)*(sum[y]+a[x]-ave);
    19          if(rand()%10000+1>T&&ans>pre)ans=pre;else sum[pos[x]]-=a[x],sum[y]+=a[x],pos[x]=y;
    20          T*=0.9;
    21      }
    22      if(ans<mn)mn=ans;
    23 }
    24 int main(){
    25     scanf("%d%d",&n,&m); inc(i,1,n)scanf("%lf",&a[i]),ave+=a[i],swap(a[i],a[rand()%i+1]);
    26     ave/=(double)m; mn=INF; inc(i,1,5000)solve();
    27     printf("%.2lf",sqrt(mn/(double)m));
    28 }

    20160421

  • 相关阅读:
    zabbix入门知识
    flask_login
    flask_数据库
    flask_web表单
    flask_模板
    flask_hello world
    1024 Hello World
    使用bat批处理文件备份postgresql数据库
    使用bat批处理文件备份mysql数据库
    在windows7下创建ftp服务站点
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5425853.html
Copyright © 2020-2023  润新知